Asynchronous Dynamic Invocation and Dispatch in C-Sharp

This page describes the asynchronous C# mapping for the ice_invoke proxy function and the Blobject class.

On this page:

Calling ice_invoke Asynchronously in C#

The asynchronous mapping for ice_invoke resembles that of the static AMI mapping. Multiple overloadings are provided to support the use of callbacks and request contexts. The return value and the parameters operation, mode, and inParams have the same semantics as for the synchronous version of ice_invoke.

Basic Asynchronous Mapping for ice_invoke in C#

The basic mapping is shown below:

C#
Ice.AsyncResult<Ice.Callback_Object_ice_invoke>
begin_ice_invoke(
    string operation,
    Ice.OperationMode mode,
    byte[] inParams);

Ice.AsyncResult<Callback_Object_ice_invoke>
begin_ice_invoke(
    string operation,
    Ice.OperationMode mode,
    byte[] inParams,
    Dictionary<string, string> context__);

bool end_ice_invoke(out byte[] outParams, AsyncResult r__);

User exceptions are handled differently than for static asynchronous invocations. Calling end_ice_invoke can raise system exceptions but never raises user exceptions. Instead, the boolean return value of end_ice_invoke indicates whether the operation completed successfully (true) or raised a user exception (false). If the return value is true, the byte sequence contains an encapsulation of the results; otherwise, the byte sequence contains an encapsulation of the user exception.

Generic Asynchronous Callback Mapping for ice_invoke in C#

The generic callback API is also available:

C#
Ice.AsyncResult begin_ice_invoke(
    string operation,
    Ice.OperationMode mode,
    byte[] inParams,
    Ice.AsyncCallback cb__,
    object cookie__);

Ice.AsyncResult begin_ice_invoke(
    string operation,
    Ice.OperationMode mode,
    byte[] inParams,
    Dictionary<string, string> context__,
    Ice.AsyncCallback cb__,
    object cookie__);

Refer to the static AMI mapping for a callback example.

Type-Safe Asynchronous Callback Mapping for ice_invoke in C#

For the type-safe callback API, you register callbacks on the AsyncResult object just as in the static AMI mapping:

C#
public class MyCallback
{
    public void responseCB(bool ret, byte[] results)
    {
        if(ret)
            System.Console.Out.WriteLine("Success");
        else
            System.Console.Out.WriteLine("User exception");
    }

    public void failureCB(Ice.Exception ex)
    {
        System.Console.Err.WriteLine("Exception is: " + ex);
    }
}

...

Ice.AsyncResult<Ice.Callback_Object_ice_invoke> r = proxy.begin_ice_invoke(...);
MyCallback cb = new MyCallback();
r.whenCompleted(cb.responseCB, cb.failureCB);

The caller invokes whenCompleted on the AsyncResult object and supplies delegates to handle response and failure. The response delegate must match the signature of Ice.Callback_Object_ice_invoke:

C#
public delegate void Callback_Object_ice_invoke(bool ret__, byte[] outParams);

Subclassing BlobjectAsync in C#

BlobjectAsync is the name of the asynchronous counterpart to Blobject:

C#
public abstract class BlobjectAsync : Ice.ObjectImpl
{
    public abstract void ice_invoke_async(
        AMD_Object_ice_invoke cb,
        byte[] inParams,
        Current current);
}

To implement asynchronous dynamic dispatch, a server must subclass BlobjectAsync and override ice_invoke_async.

The first argument to the servant's member function is a callback object of type Ice.AMD_Object_ice_invoke, shown here:

C#
namespace Ice
{
    public interface AMD_Object_ice_invoke
    {
        void ice_response(bool ok, byte[] outParams);
        void ice_exception(System.Exception ex);
    }
}

Upon a successful invocation, the servant must invoke ice_response on the callback object, passing true as the first argument and encoding the encapsulated operation results into outParams. To report a user exception, the servant invokes ice_response with false as the first argument and the encapsulated form of the exception in outParams.

In the dynamic dispatch model, the ice_exception function must not be used to report user exceptions; doing so results in the caller receiving UnknownUserException.

See Also