Check if a async call to service is still alive

1.5k Views Asked by At

I have an async service

The service contract defined like:

[ServiceBehavior(InstanceContextMode = InstanceContext.PerCall]
Myservice

My client is defined like:

MyServiceClient task= null;
InstanceContext instanceContext = new InstanceContext(this);

task = new MyServiceClient(instanceContext);

task.MyMethod();

And the client class implements the call back methods (finish, progress etc...).

It's works fine, but if I call to the method, and she start running on the server and I shut down the server,I can't know the status of my call, and the client still think that the methods still running.

So, how can I check if this call is still running?

Thanks for helpers :)

Edit:

CallBack Interface:

public interface IServiceCallback
{
   [OperationContract(IsOneWay=true)]
   void NotifyFinished();

   [OperationContract(IsOneWay=true)]
   void NotifyProgress(int x);

   [OperationContract(IsOneWay=true)]
   void NotifyFailed(Exception exception);

}

Service Interface:

[ServiceContract(CallbackContract = typeof (IServiceCallback)]
public interface IAsyncService
{
    [OperationContract(IsOneWay=true)]
    void AsyncRunning();
}

Service Class:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class AsyncService : IAsyncService
{
    private IServiceCallback ServiceCallback {get; set;}

    public void AsyncRunningProxy ()
    {
        for(int x=0; x<100 ; x++)
        {
            AsyncService.NotifyProgress(x);
        }
    }

    private void EndMethod(IAsyncResult res)
    {
         AsyncResult result = (AsyncResult)res;
        try
        {
            ((dynamic)result.AsyncDelegate).EndInvoke(res);
             AsyncService.NotifyFinished();
        }
        catch (Exception e)
        {
            AsyncService.NotifyFailed(e);
        }

    }

    public void AsyncRunning ()
    {
        ServiceCallback = OperationContext.Current.GetCallBackChannel<IServiceCallback>();
        Action action = AsyncRunningProxy;

        action.BeginInvoke(EndMethod, null); 
    }
}

Client Class:

public class ServiceRunner : IServiceCallback
{
    private ManualResetEvent reset {get; set;}

    public ServiceRunner()
    {
         reset = new ManualResetEvent(false);
    }

    public void Run()
    {
        AsyncServiceClient client = null;

        InstanceContext instanceContext = new InstanceContext(this);

        client = new AsyncServiceClient(instanceContext);

        client.AsyncRunning();

        reset.WaitOne();
    }

    public void NotifyProgress(int x)
    {
        Console.WriteLine(x);
    }

    public void NotifyFinished()
    {

    }

    public void NotifyFailed(Exception e)
    {
        Console.WriteLine(e.Message);
        reset.Set();
    }

}

Edit: new client Class:

Client Class:

public class ServiceRunner : IServiceCallback
{
    private ManualResetEvent reset { get; set; }

    private string IsRunning { get; set; }

    public ServiceRunner()
    {
         reset = new ManualResetEvent(false);
         IsRunning = true;   
    }

    public void Run()
    {
        AsyncServiceClient client = null;

        InstanceContext instanceContext = new InstanceContext(this);

        client = new AsyncServiceClient(instanceContext);

        client.AsyncRunning();

        new Thread(()=>
        {
            while(IsRunning)
            {
                try
                {
                    client.IsAlive();
                    Thrad.Sleep(60 * 1000);
                }
                catch (Exception e) // The server is not responding.
                {
                    NotifyFailed(e);
                    return;
                }
            }
        }).Start();

        reset.WaitOne();
    }

    public void NotifyProgress(int x)
    {
        Console.WriteLine(x);
    }

    public void NotifyFinished()
    {
        IsRunning = false;
        reset.Set();
    }

    public void NotifyFailed(Exception e)
    {
        IsRunning = false;
        Console.WriteLine(e.Message);
        reset.Set();
    }

}
2

There are 2 best solutions below

0
On

In order to have more control of your clients request to the service, you should be able to use the inbuilt Task and Async support to monitor and if necessary handle connection delays.

The support for generating Task-based operations on the client side will be available to users who rely on proxies generated by our client generation tools (svcutil.exe or Add Service Reference), as well as to users who prefer to directly use ChannelFactory

The following code provides a rough example:

Task<string> task = new MyServiceClient().MyMethod();
if (task == await Task.WhenAny(task, Task.Delay(1000)))
{
     Console.WriteLine(await task);
}
else
{
    // handle delay …
}

Refer to the following MSDN blog entry for more information: http://blogs.msdn.com/b/endpoint/archive/2010/11/13/simplified-asynchronous-programming-model-in-wcf-with-async-await.aspx

Regards,

7
On

As @adkSerenity mention you may implement timeout logic, but I guess your question not about that.

The callback method will be(and should be) called in case of exception for example connection lose or internal connection time out.

    private static void CallbackSample(IAsyncResult asynchronousResult)
    {  
      try
      {
        // State of request is asynchronous.
        RequestState myRequestState=(RequestState) asynchronousResult.AsyncState;
        HttpWebRequest  myHttpWebRequest2=myRequestState.request;
        myRequestState.response = (HttpWebResponse);
//next line may throw exception
myHttpWebRequest2.EndGetResponse(asynchronousResult); 

      }
      catch(WebException e)
      {

      }
    }

So async communication looks like fire and forget. Your callback method will be called when you get the result(exception too), but if you decide not handle it(custom time out logic) you must "foret" about callback processing. No way to check is alive(except of course custom api).