Archived

This forum has been archived. Please start a new discussion on GitHub.

IceStorm in a Windows GUI App

Hi All,

have a quick question regarding integrating ICEStorm into a windows GUI app. What method actually gets executed in my code based upon the Ice Dispatcher.BeginInvoke call?

For example, per the below code snippets from your documentation, the parm 'action' is a function pointer/reference to the method the main GUI thread will call when it processes this message resulting from the BeginInvoke call. What does action actually reference? If I wrapped the subscriber demo code in a windows GUI app, what method (in subscriber) would get executed from the below? I'd want it to execute the tick method in the ClockI interface, but that method requires parms, and action is a parmless method?

FWIW, we are NOT using SilverLight, so this is/would be a pure winforms based app.

Thanks in advance

David


public partial class MyWindow : Window
{
private void Window_Loaded(object sender, EventArgs e)
{
Ice.Communicator communicator = null;

try
{
Ice.InitializationData initData = new Ice.InitializationData();
//
initData.dispatcher = delegate(System.Action action, Ice.Connection connection)
{
Dispatcher.BeginInvoke(DispatcherPriority.Normal, action);
};
communicator = Ice.Util.initialize(initData);
}
catch(Ice.LocalException ex)
{
// ...
}
}

// ...
}

Comments

  • xdm
    xdm La Coruña, Spain
    Hi

    See Dispatching Invocations to User Threads - Ice 3.4 - ZeroC
    initData.dispatcher = delegate(System.Action action, Ice.Connection connection)
      {
           Dispatcher.BeginInvoke(DispatcherPriority.Normal, action);
      };
    

    Here you configure the dispatcher used by all incoming operations, and by calling BeginInvoke you run that invocations in the GUI thread, that is what you want if you want to manipulate GUI elements directly from your servant or callback implementations.

    For example in subscriber demo the invocation of 'tick' will go throw this dispatcher, and will be safe to modify the GUI from your 'tick' method implementation.
  • Hi Jose,

    thanks for the quick reply. So just to make sure, the main windows GUI message handler, upon recieving this 'message', via BeginInvoke, will know to call the tick method in ClockI without any additional coding/logic required?

    What if I had another method in ClockI, say 'tock' that had a signature like this
    public override void tock(int count, Ice.Current current)

    forgetting for a moment about any setup I would have to do to add tock to the ClockI class/interface, would the windows GUI message handler know to call tock appropriately?

    Thanks
    David
  • mes
    mes California
    Hi David,

    The dispatcher facility provides a way for an application to postpone the execution of Ice activities, so that they can be executed by a specific thread rather than a thread from the Ice run time.

    The action argument to the delegate encapsulates the activity that the Ice run time needs to execute. This includes dispatching an incoming request to a servant (such as delivering an IceStorm event), invoking the completion callback for an asynchronous outgoing request, and other tasks.

    As long as your delegate executes every action that comes along, the Ice run time will continue to perform as expected, with the added benefit that these activities are performed in a thread of your choosing. In a GUI, this allows you to redirect these activities into the GUI thread, so that you can safely manipulate GUI elements from within servant methods or asynchronous completion callbacks.

    Let me know if anything is still unclear.

    Regards,
    Mark
  • Thanks Mark,

    just wanted to clarify. Good to go.

    David
  • xdm
    xdm La Coruña, Spain
    Hi,

    To be clear, when Ice run time receive an operation invocation, it uses the configured dispatcher to dispatch it. That doesn't require extra logic, you configure a dispatcher and Ice run time uses that.
    What if I had another method in ClockI, say 'tock' that had a signature like this
    public override void tock(int count, Ice.Current current)

    If you just define the method in ClockI, that is a local method and the dispatcher don't interact with that.

    If you define the method in Clock interface in Clock.ice and implement it in ClockI, that is a remote method, and when you get a remote invocation to 'tock', it will go throw the configure dispatcher. And that is the same for all operation invocations your application receive.
  • Thanks Jose,

    exact answer I was looking for

    David
  • can I set the Communicator dispatcher in my .run(...) method

    Hi,

    One more quick question regarding having ICE servants running on the windows GUI thread.

    I've got all the code down, now issue is that if I use the App class to initialize the communicator, the communicator is already initialized by the time it executes my App.run(..) method. So my guess is is that I can't execute code like this

    //we have to do this to be able to modify the dispatcher
    // ic is declared above like this Ice.Communicator ic;
    Ice.InitializationData idata = new Ice.InitializationData();
    idata.dispatcher = theform.dispatchICEtoGUI;
    ic = Ice.Util.initialize(idata);


    in my run method as the communicator has already been initailized in App.main.

    If my guess is correct, I need to NOT use App.main() but rather just initialize ICE via my code. This will work, but I'm not sure what I need to do aside from a basic code as described in the documentation (see below). For example, I'm not sure what I need to do to process the parms in the 'config.sub' file

    YOUR DOCUMENTATION THAT DESCIBES A BASIC ICE STARTUP
    C#
    using System;

    public class Server
    {
    public static void Main(string[] args)
    {
    int status = 0;
    Ice.Communicator communicator = null;

    try {
    communicator = Ice.Util.initialize(ref args);
    // ...
    } catch (Exception ex) {
    Console.Error.WriteLine(ex);
    status = 1;
    }
    if (communicator != null) {
    try {
    communicator.destroy();
    } catch (Exception ex) {
    Console.Error.WriteLine(ex);
    status = 1;
    }
    }
    Environment.Exit(status);
    }
    }



    Any help appreciated

    Thanks in advance
    David
  • mes
    mes California
    Hi David,

    You're on the right track. Have a look at the C# code in democs/Ice/wpf for a complete client implementation.

    Regards,
    Mark
  • Hi,

    Thanks for the reply Mark. Seems I am properly initing the communicator, now my GUISubscriber app hangs when I try to create my TopicManagerPrx.

    Here is my code:

    //create the icestorm topix manager
    Ice.ObjectPrx junk = ic.propertyToProxy("TopicManager.Proxy");
    IceStorm.TopicManagerPrx manager = IceStorm.TopicManagerPrxHelper.checkedCast(junk);
    if (manager == null)
    {
    Console.WriteLine("invalid proxy");
    ic.destroy();
    return;
    }


    I am hanging at the bolded statement. I can't find any documentation for TopicManagerPrxHelper, so I turn to you!

    (BTW, the search functionality seems to be less functional that it ought to be. If I do a search on 'TopicManagerPrx' via the search on the url 'http://doc.zeroc.com/display/Doc/Home'
    I get no hits, but clearly TopicManagerPrx' is mentioned in the documentation)

    Thanks in advance
    David
  • mes
    mes California
    Hi David,

    One limitation of using a dispatcher is that you must not make any blocking calls from within the dispatch thread. We mention this in the notes at the bottom of this page.

    In your example, the call to checkedCast causes a synchronous twoway invocation on the remote object. With the dispatcher installed, the reply to this request will be processed by your dispatch thread (i.e., the GUI thread). However, the GUI thread is currently blocked waiting for that reply to be processed, and hence we have deadlock.

    The simplest solution is to replace the checkedCast with an uncheckedCast. Of course, by doing so, your client is no longer confirming that the target object does in fact implement the TopicManager interface. In any event, if some configuration error causes the client to communicate with the wrong object, the client will discover it quickly enough when the next remote invocation fails, so using uncheckedCast is a relatively safe alternative.

    Regards,
    Mark