异步回调在哪个线程上运行?
我正在进行多次 HttpWebRequest.BeginGetResponse
调用,并在 BeginGetResponse
的回调方法中调用 EventHandler。在EventHandler中,有测试下载是否成功的逻辑。如果没有,它会尝试重新下载 Html。我注意到生成了很多线程,尤其是在出现错误时。那么,异步回调在哪个线程上运行?
无论如何,我可以在原始线程上调用 EventHandler 吗?如果这不可能,我可以在 UI 线程上调用它吗?
谢谢!
I'm making several HttpWebRequest.BeginGetResponse
calls, and in the callback method of the BeginGetResponse
, I'm invoking an EventHandler. In the EventHandler, there is logic to test if the download was successful. If not, it tries to redownload the Html. I'm noticing lots of threads being generated especially when there are errors. So, on which thread do the Async Callbacks run?
Is there anyway I can invoke the EventHandler on the original thread? If that is not posible, can I invoke it on the UI thread?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
回调是在线程池线程上进行的。 .NET 中没有机制可以使代码在特定线程上运行。这是很难做到的,你不能在线程繁忙时中断它并让它运行一些代码。这会导致可怕的重入问题,而锁无法解决。
线程必须处于空闲状态,而不是主动改变程序的状态。有一种线程具有这种行为方式,即 Winforms 或 WPF 应用程序中的 UI 线程。这也是必须处理本质上线程不安全的对象(任何与 UI 相关的对象)的线程。这并非巧合。
这两个类库都可以将工作线程的调用编组到 UI 线程,特别是帮助以线程安全的方式更新 UI。在Winforms中,您使用Control.Begin/Invoke(),在WPF中,您使用Dispatcher.Begin/Invoke()。 BackgroundWorker 是一个方便的类,无需显式管理编组即可完成此任务。但不适合 I/O 完成回调。
Callbacks are made on a threadpool thread. There is no mechanism in .NET to make code run on a specific thread. That is very hard to come by, you can't just interrupt a thread while it is busy and make it run some code. That causes horrible re-entrancy problems that a lock cannot solve.
A thread must be in an idle state, not actively mutating the state of the program. There's one kind of thread that behaves that way, the UI thread in a Winforms or WPF app. That's also the thread that has to deal with objects that are fundamentally thread-unsafe, anything related to the UI. This is not a coincidence.
Both class libraries make it possible to marshal a call from a worker thread to the UI thread, specifically to help getting the UI updated in a thread-safe way. In Winforms you use Control.Begin/Invoke(), in WPF you use Dispatcher.Begin/Invoke(). BackgroundWorker is a handy class to get this done without explicitly managing the marshaling. But isn't suitable for I/O completion callbacks.
“在原始线程上”是什么意思?哪个原帖?您可以使用
Control.BeginInvoke
或Dispatcher.BeginInvoke
编组到 UI 线程。您不能编组到任意线程 - 它必须有一些东西,例如等待工作的消息泵。至于在哪个线程上执行 HttpWebRequest 异步回调 - 我希望是通用线程池工作线程,或者可能是 IO 完成端口线程。
What do you mean by "on the original thread"? Which original thread? You can marshal to the UI thread using
Control.BeginInvoke
orDispatcher.BeginInvoke
. You can't marshal to an arbitrary thread - it has to have something like a message pump waiting for work.As for which thread
HttpWebRequest
async callbacks are executed on - I would expect either a general thread pool worker thread, or possibly an IO completion port thread.使用开始/结束异步模式,请注意多种任务可以在调用它们的线程上完成。当您调用 BeginXXX 时,它会返回一个布尔值,表示调用线程上的任务是否已完成。
基本答案是,它可以是任何线程。
Using the Begin/End Async pattern, be aware that it's possible for many kinds of tasks to complete on the thread they were called from. When you call BeginXXX, it returns a boolean that signifies if the task was completed on the calling thread or not.
The basic answer is, it could be any thread.
如果您使用 WPF,则可以使用 Dispatcher 来调用 UI 线程上的逻辑。
否则,(如果不在 WPF 中)您可以使用 SyncrhronizationContext 来完成同样的事情。
If you are using WPF you can use the Dispatcher to invoke your logic on the UI thread.
Otherwise, (if not in WPF) you could use a SyncrhronizationContext to accomplish the same thing.