与命名管道和WCF服务的进程间通信:线程问题

时间:2022-01-17 16:50:47

I have two processes: one GUI, the other CUI. Each of them host a simple WCF service and they communicate with each other via name pipes.

我有两个进程:一个GUI,另一个CUI。它们中的每一个都托管一个简单的WCF服务,并通过名称管道相互通信。

There are two buttons and a progress bar in the GUI application. 与命名管道和WCF服务的进程间通信:线程问题

GUI应用程序中有两个按钮和一个进度条。

The "Start Running" button tells the CUI to run a task for 30 seconds. The CUI reports its progress back to the GUI, so the progress bar can be updated. The "Print" button tells the CUI to print a string.

“开始运行”按钮告诉CUI运行任务30秒。 CUI将其进度报告回GUI,因此可以更新进度条。 “打印”按钮告诉CUI打印字符串。

Now if we press the "Print" button for a few times, it's fine, the CUI will print strings: 与命名管道和WCF服务的进程间通信:线程问题

现在,如果我们按下“打印”按钮几次,没关系,CUI将打印字符串:

Then if I press the "start running" button, the CUI will print the progress to the console and report the progress back to the GUI and the progress bar gets updated: 与命名管道和WCF服务的进程间通信:线程问题

然后,如果我按下“开始运行”按钮,CUI会将进度打印到控制台并将进度报告回GUI,进度条会更新:

Then I can press the "Print" button for a couple more times, and it works: 与命名管道和WCF服务的进程间通信:线程问题

然后我可以多按几次“打印”按钮,它可以工作:

This all seems good.

这一切似乎都很好。

But if I restart those two processes, and click the "Start Running" button first, then click the "Print" button, then both processes will be frozen: 与命名管道和WCF服务的进程间通信:线程问题

但是,如果我重新启动这两个进程,然后先单击“开始运行”按钮,然后单击“打印”按钮,则两个进程都将被冻结:

It looks like a threading issue.

它看起来像一个线程问题。

So it seems like if I start with clicking the print button, then everything works. But if I start with clicking the start running button, then there'll be a dead lock. Why is that?

所以看起来如果我开始点击打印按钮,那么一切正常。但是,如果我开始点击开始运行按钮,那么就会有一个死锁。这是为什么?

You can download this sample from here : http://files.cnblogs.com/cuipengfei/SampleFor*.zip

您可以从这里下载此示例:http://files.cnblogs.com/cuipengfei/SampleFor*.zip

1 个解决方案

#1


1  

The deadlock appears when you're calling worker.Print() as it doesn't create a new object for the worker, but tries to reuse the same one. If you put that call in another thread, then you see that this call is executed once worker.RunTask(30) finishes.

当您调用worker.Print()时会出现死锁,因为它不会为worker创建新对象,但会尝试重用相同的对象。如果你把那个调用放在另一个线程中,那么你会看到一旦worker.RunTask(30)完成就会执行这个调用。

First I was thinking of changing the InstanceContextMode.Single to InstanceContextMode.PerCall, so it creates one object per call instead of using the same object for all calls. This didn't resolve the problem.

首先,我考虑将InstanceContextMode.Single更改为InstanceContextMode.PerCall,因此它为每次调用创建一个对象,而不是为所有调用使用相同的对象。这并没有解决问题。

Re-testing your provided case study, it also works if you let finish worker.RunTask(30). So I think the problem occurs, if you have never finished a call before invoking a 2nd call. Then it tries to reuse the same server instance. Once you fully finished one call, it works as expected.

重新测试您提供的案例研究,如果您让完成的工作人员也可以工作.RunTask(30)。所以我认为问题出现了,如果你在调用第二个电话之前从未完成过电话。然后它尝试重用相同的服务器实例。完成一个呼叫后,它会按预期工作。

However, what solves your problem is to open multiple connections to your server:

但是,解决您的问题的方法是打开与服务器的多个连接:

NetNamedPipeBinding binding2 = new NetNamedPipeBinding();
worker2 = ChannelFactory<IWorker>.CreateChannel(binding2, endpointAddress);

Then use this for accessing the print operation:

然后使用它来访问打印操作:

worker2.Print();

#1


1  

The deadlock appears when you're calling worker.Print() as it doesn't create a new object for the worker, but tries to reuse the same one. If you put that call in another thread, then you see that this call is executed once worker.RunTask(30) finishes.

当您调用worker.Print()时会出现死锁,因为它不会为worker创建新对象,但会尝试重用相同的对象。如果你把那个调用放在另一个线程中,那么你会看到一旦worker.RunTask(30)完成就会执行这个调用。

First I was thinking of changing the InstanceContextMode.Single to InstanceContextMode.PerCall, so it creates one object per call instead of using the same object for all calls. This didn't resolve the problem.

首先,我考虑将InstanceContextMode.Single更改为InstanceContextMode.PerCall,因此它为每次调用创建一个对象,而不是为所有调用使用相同的对象。这并没有解决问题。

Re-testing your provided case study, it also works if you let finish worker.RunTask(30). So I think the problem occurs, if you have never finished a call before invoking a 2nd call. Then it tries to reuse the same server instance. Once you fully finished one call, it works as expected.

重新测试您提供的案例研究,如果您让完成的工作人员也可以工作.RunTask(30)。所以我认为问题出现了,如果你在调用第二个电话之前从未完成过电话。然后它尝试重用相同的服务器实例。完成一个呼叫后,它会按预期工作。

However, what solves your problem is to open multiple connections to your server:

但是,解决您的问题的方法是打开与服务器的多个连接:

NetNamedPipeBinding binding2 = new NetNamedPipeBinding();
worker2 = ChannelFactory<IWorker>.CreateChannel(binding2, endpointAddress);

Then use this for accessing the print operation:

然后使用它来访问打印操作:

worker2.Print();