我有两个进程:一个GUI,另一个CUI。 它们每个都托管一个简单的WCF服务,并通过名称管道相互通信。
GUI应用程序中有两个按钮和一个进度条。
“开始运行”按钮告诉CUI运行任务30秒。 CUI将其进度报告回GUI,因此可以更新进度条。 “打印”按钮告诉CUI打印字符串。
现在如果我们按下“打印”按钮几次,没关系,CUI会打印字符串:
然后,如果我按下“开始运行”按钮,CUI会将进度打印到控制台并将进度报告回GUI,进度条会更新:
然后我可以多次按下“打印”按钮,它可以工作:
这一切似乎都很好。
但是,如果我重新启动这两个进程,然后先单击“开始运行”按钮,然后单击“打印”按钮,则两个进程都将被冻结:
这看起来像是一个线程问题。
所以看起来如果我从点击打印按钮开始,那么一切正常。 但是,如果我开始点击开始运行按钮,那么就会出现死锁。 那是为什么?
您可以从此处下载此示例:http://files.cnblogs.com/cuipengfei/SampleForStackOverflow.zip
答案 0 :(得分:1)
当您调用worker.Print()时会出现死锁,因为它不会为worker创建新对象,但会尝试重用相同的对象。如果你把那个调用放在另一个线程中,那么你会看到一旦worker.RunTask(30)完成就会执行这个调用。
首先,我考虑将InstanceContextMode.Single更改为InstanceContextMode.PerCall,因此它为每次调用创建一个对象,而不是为所有调用使用相同的对象。这并没有解决问题。
重新测试您提供的案例研究,如果您让完成的工作人员也可以工作.RunTask(30)。所以我认为问题出现了,如果你在调用第二个电话之前从未完成过电话。然后它尝试重用相同的服务器实例。完成一个电话后,它会按预期工作。
但是,解决您问题的方法是打开与服务器的多个连接:
NetNamedPipeBinding binding2 = new NetNamedPipeBinding();
worker2 = ChannelFactory<IWorker>.CreateChannel(binding2, endpointAddress);
然后使用它来访问打印操作:
worker2.Print();