TPL可以在多个线程上运行任务吗? [英] Can the TPL run the Task on more than one thread?
问题描述
欢迎针对Mono/Xamarin的答案.
Mono/Xamarin-specific answers are welcomed.
我正在使用Task.Run()运行System.Threading.Tasks. TPL将在任务执行期间将创建的任务分配给单个线程吗?还是创建的任务在运行时会被抢占,然后在另一个线程上再次进行调度?
I'm running System.Threading.Tasks using Task.Run(). Will The TPL assign the created task to a single thread for the life of the task's execution? Or is it possible that the created task will get preempted while running, and then be scheduled again on a different thread?
Thread.CurrentThread.ManagedThreadId在任务的生命周期中会保持不变吗?
Will Thread.CurrentThread.ManagedThreadId be constant over the life of a Task?
对于长期运行的任务,答案是否有所不同?
Is the answer different for long-running tasks?
在这方面是否有办法控制TPL行为?
Is there a way to control TPL behavior in this regard?
推荐答案
TPL将在任务执行的整个生命周期中将创建的任务分配给单个线程吗?
Will The TPL assign the created task to a single thread for the life of the task's execution?
指南是,工作的 synchronous 部分在单个线程上运行.因此,如果将同步委托传递给Task.Run
,它将全部在单个线程上运行:
The guideline is that synchronous portions of work run on a single thread. So, if you pass a synchronous delegate to Task.Run
, it will all run on a single thread:
await Task.Run(() => Thread.Sleep(5000)); // same thread after sleep
但是,如果您有异步代码,则每个await
都是代码中该方法被挂起的位置.方法恢复后,将在线程池线程(可能是其他线程)上恢复.
However, if you have asynchronous code, every await
is a location in the code where the method is suspended. When the method resumes, it will resume on a thread pool thread (which may be a different thread).
await Task.Run(async () => await Task.Delay(5000)); // thread may change
长时间运行的标志(不能传递给Task.Run
)不会影响此行为,因为它仅适用于第一个同步部分.
The long-running flag (which cannot be passed to Task.Run
) does not affect this behavior because it only applies to the first synchronous portion.
控制此操作的通常方法是使用自定义TaskScheduler
或SynchronizationContext
.但是,在走这条路之前,您可能需要考虑另一种方法.与将方法强制返回到同一线程相比,应该有更好的解决方案.例如,仿射仿射同步原语都具有与async
兼容的等效项,可以用闭包/类字段/逻辑调用上下文等替换线程本地存储.
The normal way to control this is by using a custom TaskScheduler
or SynchronizationContext
. However, before going down that road, you may want to consider an alternative approach. There should be a better solution than forcing the method back onto the same thread. For example, thread-affine synchronization primitives all have async
-compatible equivalents, thread-local storage can be replaced by closures / class fields / logical call context, etc.
这篇关于TPL可以在多个线程上运行任务吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!