检查对服务的异步调用是否仍然存在

时间:2013-11-04 09:41:29

标签: c# wcf asynchronous callback instancecontextmode

我有异步服务

服务合同定义如下:

[ServiceBehavior(InstanceContextMode = InstanceContext.PerCall]
Myservice

我的客户定义如下:

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

task = new MyServiceClient(instanceContext);

task.MyMethod();

客户端类实现回调方法(完成,进度等)。

它工作正常,但如果我调用该方法,并且她开始在服务器上运行并关闭服务器,我无法知道我的调用状态,并且客户端仍然认为方法仍在运行。

那么,我该如何检查此呼叫是否仍在运行?

感谢帮助者:)

编辑:

CallBack界面:

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

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

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

}

服务接口:

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

服务类:

[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); 
    }
}

客户类:

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();
    }

}

编辑:新客户类:

客户类:

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 个答案:

答案 0 :(得分:0)

为了更好地控制客户端对服务的请求,您应该能够使用内置的Task和Async支持来监视并在必要时处理连接延迟。

对于依赖我们的客户端生成工具(svcutil.exe或添加服务参考)生成的代理的用户以及喜欢直接使用的用户,可以使用客户端生成基于任务的操作的支持ChannelFactory

以下代码提供了一个粗略的例子:

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

有关详细信息,请参阅以下MSDN博客条目: http://blogs.msdn.com/b/endpoint/archive/2010/11/13/simplified-asynchronous-programming-model-in-wcf-with-async-await.aspx

此致

答案 1 :(得分:0)

正如@adkSerenity所提到的,你可以实现超时逻辑,但我想你的问题与此无关。

如果例外连接丢失或内部连接超时,将调用(并且应该)调用回调方法。

    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)
      {

      }
    }

因此,异步通信看起来像 fire and forget 。当你得到结果时也会调用你的回调方法(例外),但是如果你决定不处理它(自定义超时逻辑),你必须“foret”关于回调处理。无法检查是否存在(当然除了自定义api)。