WCF:使用异步方法在回调(同一客户端)上调用服务方法

时间:2013-03-27 14:10:37

标签: wcf-callbacks asynchronous-wcf-call

我正在做一些WCF实验,以了解我可以使用会话,回调和TPL运行多远。其中一个实验有奇怪的结果...... 该服务使用双向绑定(NetTcpBinding)实现,并实现通知 作为回调。 预期的行为应该是:

  1. 客户端以同步方式调用服务(Do)上的方法
  2. 服务以同步方式在客户端上调用回调
  3. 客户端(在回调中)以异步方式在服务上调用第二个方法
  4. 该服务需要一个会话,InstanceContext是PerSession,并发模式是Single。 在这种情况下,我知道,在回调的上下文中,我无法以同步方式调用任何服务方法(在同一客户端上),因此代码可以是:

    [ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(INotificationCallback))]
    public interface INotificationService
    {
        [OperationContract]
        int Do(int value);
    
        [OperationContract]
        int ReDo(int value);
    }
    
    public interface INotificationCallback
    {
        [OperationContract(IsOneWay = true)]
        void Notify(int value);
    }
    
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)]
    public class NotificationService : INotificationService
    {
            public int Do(int value)
            {
                var notificationCallback = OperationContext.Current.GetCallbackChannel<INotificationCallback>();
                //Task.Run(() => notificationCallback.Notify(value * 2));
                notificationCallback.Notify(value * 2);
                Thread.Sleep(1000);
                return value * 2;
            }
    
            public int ReDo(int value)
            {
                return value + 1;
            }
    }
    

    在客户端上实现回调接口:

    class CallbackInstance : INotificationServiceCallback
    {
        public NotificationServiceClient Client { get; set; }
    
        #region Implementation of INotificationServiceCallback
    
        public void Notify(int value)
        {
            Console.WriteLine("Notified: {0}", value);
            Task<int> task = Client.ReDoAsync(value);
            task.ContinueWith(t => Console.WriteLine("In Notify - ReDo({0}): {1}", value, t.Result));
        }
    
        #endregion
    }
    

    运行所有代码的主要方法:

    static void Main(string[] args)
    {
        CallbackInstance callback = new CallbackInstance();
        NotificationServiceClient client = new NotificationServiceClient(new InstanceContext(callback));
        callback.Client = client;
    
        int result = client.Do(10);
        Console.WriteLine("Do({0}): {1}", 10, result);
    
        Console.ReadLine();
    }
    

    在我认识的Notify方法实现中的行:

    Task<int> task = Client.ReDoAsync(value);
    task.ContinueWith(t => Console.WriteLine("In Notify - ReDo({0}): {1}", value, t.Result));
    

    应该打破死锁但是......不,当调用ReDoAsync时会抛出异常,说“此操作会死锁,因为直到 当前消息完成处理...“。是的,亲爱的,我知道。事实上,我想以异步的方式回拨服务以绕过问题, 它不起作用。

    但让我疯狂的是,改变一点代码使它像魅力一样工作;而不是我试过的ReDoAsync调用:

    Task<int> task = Task.Run(() => Client.ReDo(value));
    

    它的工作原理! 所以问题是:客户端方法的异步版本是否应该使调用与有效的调用相同或类似? 如果没有,那么客户端方法的Async版本究竟是什么呢?

    感谢。

0 个答案:

没有答案