【问题标题】:Check if a async call to service is still alive检查对服务的异步调用是否仍然存在
【发布时间】:2013-11-14 21:50:26
【问题描述】:

我有一个异步服务

服务合同定义如下:

[ServiceBehavior(InstanceContextMode = InstanceContext.PerCall]
Myservice

我的客户定义如下:

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

task = new MyServiceClient(instanceContext);

task.MyMethod();

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

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

那么,我如何检查此调用是否仍在运行?

感谢帮助:)

编辑:

回调接口:

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

}

【问题讨论】:

    标签: c# wcf asynchronous callback instancecontextmode


    【解决方案1】:

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

    依赖于我们的客户端生成工具(svcutil.exe 或添加服务参考)生成的代理的用户,以及喜欢直接使用通道工厂

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

    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

    问候,

    【讨论】:

      【解决方案2】:

      正如@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)
            {
      
            }
          }
      

      所以异步通信看起来像一劳永逸。当你得到结果时你的回调方法会被调用(也有异常),但是如果你决定不处理它(自定义超时逻辑)你必须“foret”关于回调处理。没有办法检查是否存在(当然自定义 api 除外)。

      【讨论】:

      • 我的问题是:当我调用我的服务上的方法时。他因某种原因停止工作(如 iisreset)。服务不会抛出异常。所以客户端无法知道该方法停止工作...
      • 你确定吗?必须抛出诸如“连接关闭”之类的异常。请提供更多代码。
      • 尝试使用 IsOneWay=false
      • 在回调中还是在服务方法中?
      • Both 和添加 AsyncPattern=true。使用 IsOneWay 属性指示操作不返回回复消息。留言msdn.microsoft.com/ru-ru/library/…
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-25
      相关资源
      最近更新 更多