views:

249

answers:

4

We are working on integrating two different applications that run simultaneously and share data. One application provides the data, the other one computes some values based off external systems and the data and has to provide it back to the first application.

We are using this library to share the data between the applications: http://grouplab.cpsc.ucalgary.ca/cookbook/index.php/Toolkits/Networking

The library basically allows to create a shared dictionary which can be queried by any application (as long as it knows the location of the shared dictionary).

So, what should happen is program A has to provide some data to program B and program B uses this data and returns some other data back to program A.

My problem is how do I make the program A wait for the response from B. In more concrete terms, I can put an object in the shared dictionary, the other program gets notified of a change in the dictionary, it can compute some attribtues and update the object in the dictionary. Program A can get notified, but I want program A to wait till it gets back this response - program A's action should be based on the returned value.

A very ugly way I see this can be done is have an infinite loop inside the function, that keeps querying the dictionary to see if the object has been udpated - if it has break out of the loop and use the object and its computed attributes. Does anyone know of a nicer solution? Thanks!

A: 

Without using other methods of IPC (since you've seemed to settle on this particular library) it would seem to me that continuous polling is about the only way. If you are willing (and able) to implement other IPC methods then you should discontinue use of the current library and just pass the data between the programs yourself.

Michael Bray
The only reason I am using that library is it seems simple to use. But if there are other IPC methods that might work better, please do let me know.
aip.cd.aish
A: 

If I understand correctly, Program A mustn't execute any additional logic until Program B has updated the value, and Program A can get a notification of said update from that system out of UCalgary.

Based on those assumptions, I'd suggest that after sending data to the shared dictionary, you start a timer whose Tick event is handled by a method that will either (a) check the dictionary for updates, or (b) check a variable that gets set by the notification that comes in from the shared dictionary library.

Once the update has been found, stop the timer, and execute the method that will pick up processing the newly updated value.

The timer is not unlike the "infinite loop" you suggested, but it has virtually no processing overhead, can be set to check at a realistic interval (be that 1 second, 1 minute, 24 hours), and can be set up to time out if things don't go as planned with Program B or the dictionary.

Jay
True, but it changes the code structure in an odd way I think. Since everything program B had to do after receiving the update from program A, must now be moved into another function that gets called from the Tick_event handler, instead of something like this:`int a = getResponseFromB(key); if (a == 1) ...`. In the tick case, the code I believe would look something like this: `getResponseFromB(key); //Function ends here}`, followed by `public void AnotherFunction(a) { ... }` which gets called from the Tick event handler.
aip.cd.aish
+1  A: 

use a ManualResetEvent.

 // machine A
 var event = new ManualResetEvent(false);
 B_Listener.OnChanged += delegate { event.Set(); }
 myDictionary.UpdateValue();
 event.WaitOne();
Jimmy
Interesting, this feels like something I need. I will look more into using it.
aip.cd.aish
+2  A: 

Using their subscription model, you are able to avoid all infinite-looping. Why would you need to loop when the only times you need to check is when something is actually updated? Since you subscribe to key patterns in the dictionary and your connection will be notified when a key fitting that pattern is updated/added, you only need to check on that.

So basically, you can use a ManualResetEvent to wait for synchronization within your own system. Here is an example of usage of ManualResetEvent:

using System;
using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        //    create the reset event -- initially unsignalled
        var resetEvent = new ManualResetEvent(false);
        //    information will be filled by another thread
        string information = null;

        //    the other thread to run
        Action infoGet = delegate
        {
            //    get the information
            information = Console.ReadLine();
            //    signal the event because we're done
            resetEvent.Set();
        };

        //    call the action in a seperate thread
        infoGet.BeginInvoke(null, null);
        //    wait for completion
        resetEvent.WaitOne();
        //    write out the information
        Console.WriteLine(information);
    }
}

To translate to your framework, you might have the subscription handler check what was updated, find that wait handle and signal it, thus advancing the proper waiting threads.

Travis Gockel
Thanks for your detailed answer. I think this would work for me. I will try implementing it to ensure it does. Thank you!
aip.cd.aish