【问题标题】:On which thread(s) does WebClient raise its events?WebClient 在哪些线程上引发其事件?
【发布时间】:2011-08-20 22:15:07
【问题描述】:

我找不到任何说明 WebClient 在哪个线程上引发其事件的文档。我进行了一些测试并确定了以下内容:

  • 如果从 UI 线程(例如从事件处理程序)调用,事件处理程序将在该线程上执行。作为测试,我在调用 OpenReadAsync 之后添加了一个无限循环。从未调用过事件处理程序。

  • 如果没有 UI 线程,例如在控制台应用程序中,事件处理程序将在线程池线程上执行。在这种情况下,如果我想为应用程序的其余部分提供一些结果,我必须注意线程问题。

这种行为是否记录在任何地方?我什么也没找到。

关于 C# 的新异步特性,我有一个基本相同的问题 - 最终,必须执行异步代码。当没有 UI 线程时,这也会产生一个线程池线程吗?反过来,这是否需要线程安全代码?

我觉得我在这里遗漏了一些东西 - 我只能找到很少的信息,但这对我来说似乎很重要。

【问题讨论】:

  • 好问题!我刚刚在使用 WebClient 时遇到了同样的问题,并在得出与您相同的结论后开始使用谷歌搜索。

标签: c# asynchronous webclient


【解决方案1】:

对于WebClient,我也没有发现它记录在案,但看到了与您相同的行为。本质上,这可以描述为“如果在调用开始时有一个活动的同步上下文,则使用它 - 否则使用线程池。”

对于 C# 5 中的异步行为,它取决于您正在等待的任何内容的实现......但我相信 Task<T> 的等待者将使用 TaskScheduler.Current 来安排延续 - 这意味着你会看到相同的行为。 (不一定只是一个设置任务调度程序的 UI 线程,但这是最明显的例子。)

当使用线程池线程时,它仍然应该是线程安全的——该方法一次只在一个线程中执行,我相信任务并行库会执行所有需要的内存屏障。

如果您对异步如何在幕后结合在一起感兴趣,您可能想阅读我的Eduasync blog series

【讨论】:

  • +1 我想我缺少的是CLR中已经有很多关于线程和同步的基础设施,可以假设WebClient使用这些基础设施。 EduaAsync 的帖子非常有趣。
【解决方案2】:

WebClient Class 实现了Event-based Asynchronous Pattern。该模式在框架设计指南中有完整描述,但 MSDN 也提供了一些提示implemented

该模式的实现者使用AsyncOperationManager 为每个异步操作创建一个AsyncOperation,并使用AsyncOperation.Post Method 引发事件。 Post MethodSynchronizationContext 上执行传递的回调,在创建 AsyncOperation 时是 current

WinForms 或 WPF 应用程序中的默认 SynchronizationContext 是 UI 线程,或控制台应用程序中的 nullWebClient Class 显然选择在后一种情况下在 ThreadPool 线程中引发事件,但这是一个实现细节。

【讨论】:

  • +1 好链接。但是,我不同意线程行为是一个实现细节。对于事件处理程序的作者来说,这是很重要的信息。
猜你喜欢
  • 2013-09-23
  • 1970-01-01
  • 2015-04-24
  • 2011-04-07
  • 2021-12-09
  • 2011-06-03
  • 1970-01-01
  • 2011-04-07
  • 1970-01-01
相关资源
最近更新 更多