【问题标题】:Async delegate for a Thread线程的异步委托
【发布时间】:2015-03-02 06:16:32
【问题描述】:

使用线程时,使用异步委托是否合乎逻辑?例如,假设我们有一个 WCF SOAP 服务,并且我们有一个使用 WCF 服务的客户端桌面应用程序。在这个应用程序中,我们需要同时具有同步和异步机制,因此有时我们需要使用线程,有时需要使用异步任务。现在假设我们需要在一个线程中消费WCF服务,那么我们可以将线程写成两种形式:

Thread Worker = new Thread (()=>{
    WCFServerClient client = new WCFServiceClient();
    var GetData = client.GetData(new GetDataRequest());
});

Thread Worker = new Thread (async ()=>{
    WCFServerClient client = new WCFServiceClient();
    var GetData = await client.GetDataAsync(new GetDataRequest());
});

哪一个更符合逻辑?我的意思是选择第二种选择是否有意义。问这个是因为第一个也不会影响应用程序的响应能力。

【问题讨论】:

  • 最好的解决方案是使用Task而不是ThreadTask worker = Task.Run(async () => ...);
  • @StephenCleary:为什么 Stephan,就 Task 更好而言。如果您不介意,请解释。 (我贪求信息)
  • 检索结果和异常更容易。完整描述on my blog.
  • @StephenCleary: 非常感谢 Stephan,我在这里“*.com/questions/28788395/establishing-proxy-tunnel”还有一个关于 Sockets 的问题,在你的博客中我还找到了 TCP/IP 常见问题解答部分,我想你可以也可以帮助我解决这个问题,如果您这样做,我将不胜感激。
  • 对不起,我不知道代理隧道。

标签: c# multithreading asynchronous


【解决方案1】:

您的两个示例都独立于 UI 线程运行,这就是为什么两个示例都不会影响响应能力。

那么行为上有什么不同呢?

在您的第二个示例中,您创建的线程将在GetData 完成之前终止。当GetData 完成后,您的代码将在另一个线程上继续,该线程取自线程池。

两者都是“合乎逻辑的”,但是否更好取决于您的使用要求。

终止您的线程然后利用线程池意味着您的线程数可能会保持较低,因此您的应用程序将使用更少的资源。

但是,如果您的应用程序已经使用了最大数量的线程池线程,那么在您等待线程池线程可用时,可能会等待处理返回的数据。

这仅在可扩展性是问题并且您正在使用尽可能多的机器资源的情况下才有意义。在大多数情况下,这根本没有明显的区别。

【讨论】:

  • 如果我没记错的话,第二个选项对 CPU 更友好,对吗?
  • @James - 我怀疑不是。第二个选项对资源更友好,但对 CPU 更友好。将所有内容捆绑起来然后将其全部分发到池线程将需要 CPU 周期。但我们说的是少量。