none
回调死锁,帮忙看一下 RRS feed

  • 问题

  • Contracts

     

        [ServiceContract(CallbackContract = typeof(IServerCallback))]
        public interface IServer
        {
            [OperationContract]
            void AddClient();
        }
    
        public interface IServerCallback
        {
            string Password
            {
                [OperationContract]
                get;
            }
        }
    

     


    实现

     

        [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
        public class Server : IServer
        {
            public void AddClient()
            {
                var client = OperationContext.Current.GetCallbackChannel<IServerCallback>();
                Console.WriteLine(client.Password);
            }
        }
    
        class Player : IServerCallback
        {
            public string Password { get; set; }
    
        }
    

     


    Client

     

            static void Main(string[] args)
            {
                Console.WriteLine("按回车启动客户端");
                Console.ReadLine();
    
                Player player = new Player();
                player.Password = "12423";
    
                ServerProxy server = new ServerProxy(player, new NetTcpBinding(),
                    new EndpointAddress("net.tcp://localhost:17017/server"));
    
                server.AddClient();
                Console.WriteLine("操作完成");
                Console.ReadLine();
            }
    

     


    结果在AddClient()时说

    此操作将死锁,因为在当前邮件完成处理以前无法收到答复。如果要允许无序的邮件处理,则在 ServiceBehaviorAttribute 上指定可重输入的或多个 ConcurrencyMode。

    server必须是单线程。我在Player上加[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]没用。

    问题代码下载http://www.box.com/s/ocne0zmxe8dxqq3dix01

    请问应该怎么做?

    2012年2月5日 11:05

答案

  • 所以在回调契约里的操作都必须是单向操作,都必须有IsOneWay=true?

    那对服务器实现所如下修改,

        [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode=ConcurrencyMode.Multiple)]
        public class Server : IServer

    为什么又运行成功了呢?不是说回调操作都必须有IsOneWay=true?我可没有修改回调契约啊。


    我重新查资料确认了一下,不需要OneWay=True.

    这个

    interface IMyContractCallback
    {
       [OperationContract]
       void OnCallback();
    }

    [ServiceContract(CallbackContract = typeof(IMyContractCallback))]
    interface IMyContract
    {
       [OperationContract]
       void DoSomething();
    }例子代码:

    WCF回调可能产生死锁情况,一般的解决办法有三种,

    1.允许服务实例多线程,不过要自己实现代码来控制服务实例的访问。比较麻烦

    2.

    直接配置服务实例并发模式为重入:[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
    class MyService : IMyContract
    {
       public void DoSomething()
       {
          IMyContractCa llback callback = OperationContext.Current.
             GetCallbackChannel<IMyContractCallback>();
          callback.OnCallback();
       }
    }

    3.就是设置回调操作

    IsOneWay=true,这样回调以后立即释放服务实例,不需要等待客户端响应消息,也可以避免死锁。


    Frank Xu Lei--谦卑若愚,好学若饥
    老徐的网站】:http://www.frankxulei.com/

    微软WCF中文技术论坛
    微软WCF英文技术论坛

    Windows Azure中文技术论坛

    2012年2月7日 13:39
    版主

全部回复