Killig orphaned processes


Badge +3

Hi,


I have an IPC event that sets off multiple child processes.


However it is possible for the Parent to finish before all of the child processes which means I end up with lots of orphaned and therefore useless processes still running.


Does you know how to kill a running process instance? I can get the serial code of the process so I can identify the instance through that but don't know how to finish them off.


Any help much appreciated as I think this may be the final hurdle before completion on my project.


Cheers


Rich


6 replies

Badge +11

There are several ways to do this, but here is the approach I generally use.


In the sub process, I have two parallel paths from the start.  One path is the normal workflow.  The other path leads to an activity that contains a SmartObject Event and two Server Code Events.  The SmartObject event writes the serial number and a key identifier to a SmartObject.  The key identifier is something that uniquely identifies this sub process as belonging to the main process.  Next it goes to the first code event, which contains a single line to set the event to asynchronous.  Setting the event to asynchronous will cause it to wait until the event is completed.  The second code event (or the Goto Activity Event found on blackmarket) simply goes to the next activity on this path.  Draw a line from the first activity to the second activity on this path even though you will be using a Goto.  The second activity on this path uses another SmartObject event to delete the entry that was written by the first SmartObject event.  This removes the information about this process from the table.


On the main path of the sub process, before it ends I also use a SmartObject event that removes information about this process from the table.  You will also need to use a Goto on this path.  I don’t recommend using a Goto for branching logic.  The reason we are using it here is Goto has the side-effect of cancelling parallel paths.  In this case, the one path will hit the async server event and wait forever until the event is completed.  If the normal path completes, this path will be cancelled by the Goto and the entry will be removed from the table.


So how do you cancel this process if the calling process is finished?  In the main workflow, before you end, put in a SmartObject event that does a List of all the sub-process serial numbers in the table that match your key information.  I modify the SmartObject event with a little custom code.  For each sub-process, this custom code takes the serial number of the async event in the child process and uses the API to invoke the Finish method on it.  This causes the async server event in the sub-process to complete and the process exits down the path that removes the entry from the table and does a Goto to cancel parallel paths.


Here’s a tip:  I put the code that uses the API to Finish the server event in an assembly in the GAC.  If you’re interested, I can post this code.


You can also search the forums because this question has been asked before and there are multiple techniques.

Badge +10
I would be intersted in seeing the code, please do post
Badge +3

Hi David,


You come to my rescue yet again, thanks.


However I don't have a full grasp of this one yet so I am going to have to ask a few more questions.


At the moment I am trying something very similar to what you are saying but without using the parallel route. When my child process starts I right out its PO Number and serial number to a smart object and then when it completes I remove these details again. This means that only incomplete process instances are stored in this SO and when I have a line rejected and need to finish the other child processes for that PO Number I use the following code for each entry with the same PO Number:


Item = conn.OpenServerItem(K2.ProcessInstance.DataFields[

"SerialNo"].Value.ToString());
Item.Finish();


However this always errors saying that it can't find a process with that serial number. My serial numbers are formatted like this: 1234_12. The first 4 digits seem to be individual to the child process so are the last 2 the key identifier that you talk about as they are the bits that don't seem to be matching up.


Also if you are using the finish code that I am usuing then how do you add the ID field to it as I though you could only pass the serial number - but if thats the last 2 digits then I suppose that makes sense.


Thamks


Rich


p.s. To see that code would be great


 

Badge +3
Sorry - Also what code do you use to set the first to asynchronous?
Badge +11

Here's the code I use to cancel an asynchronous server event.  I put this in an assembly in the GAC: 


 public static bool FinishServerEvent(string k2server, string sn)
        {
            bool bResult = false;
            SourceCode.Workflow.Client.Connection conn = null;
            SourceCode.Workflow.Client.ServerItem subtask = null;
            SourceCode.Workflow.Client.ConnectionSetup cs = new SourceCode.Workflow.Client.ConnectionSetup();


            try
            {
                cs.ConnectionString = k2server;
                conn = new SourceCode.Workflow.Client.Connection();
                conn.Open(cs);


                subtask = conn.OpenServerItem(sn);
                if (subtask != null)
                {
                    subtask.Finish();
                    bResult = true;
                }
            }
            finally
            {
                if (conn != null) conn.Close();
            }


            return bResult;


        }


 


/////Here's the code to make a server event asynchronous:


K2.Synchronous = false;

Badge +9
Just one thing to add to David's suggestion about async server event.  The identity that Finishes an async server event must be granted "Server Event' permissions for that process in K2 Workspace.  In this example I believe that should be the K2 service account.

Reply