views:

207

answers:

1

I have a WCF service running, I added a reference to the service by using Add Service Reference in the solution explorer, and I checked the box for create asynchronous operations.

My call works fine, I have a two way channel that reports back some events from the server and I am receiving the events. However, when the asynchronous task finishes in my callback handeler I get the error Unable to cast object of type 'SendAsyncResult' to type 'System.Runtime.Remoting.Messaging.AsyncResult'.

Code that calls the method.

DatabaseManagement.DatabaseManagementClient d = new DatabaseManagement.DatabaseManagementClient(new InstanceContext(new DatabaseManagementCallback()));
d.Open();
d.BeginCreateDatabase("", "PreConfSA", "_test", new AsyncCallback(BeginCreateDatabaseCallback), null);

The Async callback

static void BeginCreateDatabaseCallback(IAsyncResult ar)
{
    AsyncResult result = (AsyncResult)ar; //Execption happens here
    DatabaseManagement.DatabaseManagementClient caller = (DatabaseManagement.DatabaseManagementClient)result.AsyncDelegate;
    Console.WriteLine(caller.EndCreateDatabase(ar));
    DatabaseManagement.AccountInfo ai = new DatabaseManagement.AccountInfo();
    //set up ai here
    Console.WriteLine(caller.UpdateInfo("", "_test", ai));
}

Execption Details

System.InvalidCastException was unhandled by user code
  Message=Unable to cast object of type 'SendAsyncResult' to type 'System.Runtime.Remoting.Messaging.AsyncResult'.
  Source=Sandbox Console
  StackTrace:
       at Sandbox_Console.Program.BeginCreateDatabaseCallback(IAsyncResult ar) in E:\Visual Studio 2010\Projects\Sandbox Console\Program.cs:line 26
       at System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously)
  InnerException: 

I don't really need the result from the EndCreateDatabase but everywhere I read it says that you must call EndYouFunctionHere() or bad things happen.

Any recomendations?

+4  A: 

The EndXxx methods generated for a service reference have the signature:

EndXxx(IAsyncResult result);

(At least they do in my environment -- are you seeing something different?)

So you don't actually need to perform the cast in order to call the EndXxx method.

However, in that case you do need some way to get the service reference (client instance) into the callback method, because you can't get at it using AsyncResult.AsyncDelegate. You can do this either by storing the proxy object in a member variable instead of a local variable, or pass it to the BeginXxx method as the asyncState:

d.BeginCreateDatabase("", "PreConfSA", "_test",
  new AsyncCallback(BeginCreateDatabaseCallback),
  d);  // passing d as asyncState instead of null

Then retrieve it from the IAsyncResult.AsyncState in the callback:

DatabaseManagement.DatabaseManagementClient caller =
  (DatabaseManagement.DatabaseManagementClient)ar.AsyncState;

This removes any assumptions about the specific implementation of IAsyncResult.

itowlson
This makes sense. What I have done in the past is wrap the generated WebServiceClient class with a application service class that holds onto my caller reference.
pattersonc