private void RunAsync()
{
string param = "Hi";
Task.Run(() => MethodWithParameter(param));
}
private void MethodWithParameter(string param)
{
}
编辑
由于需求旺盛,我必须注意,Task
启动将与调用线程并行运行。假设默认值TaskScheduler
将使用.NET ThreadPool
。无论如何,这意味着您需要考虑传递给的任何参数,Task
因为多个线程可能同时访问它们,从而使它们处于共享状态。这包括在调用线程上访问它们。
在我上面的代码中,这种情况完全没有意义。字符串是不可变的。这就是为什么我以它们为例。但是说你不使用String
...
一种解决方案是使用async
和await
。默认情况下,这将捕获SynchronizationContext
调用线程的,并在调用后将方法的其余部分创建一个延续await
并将其附加到created Task
。如果此方法在WinForms GUI线程上运行,则其类型为WindowsFormsSynchronizationContext
。
延续将在回传到捕获的内容之后运行SynchronizationContext
-再次默认情况下。因此,您将回到await
调用之后开始的线程上。您可以通过多种方式更改此设置,特别是使用ConfigureAwait
。总之,该方法的其余部分将不会继续,直到之后的Task
已完成了对另一个线程。但是调用线程将继续并行运行,而不是其余方法。
等待完成本方法其余部分的等待可能会,也可能不会。如果该方法中的任何内容以后Task
都无法访问传递给的参数,则您可能根本不想使用await
。
或者,也许您稍后在方法中使用这些参数。没有理由await
立即这样做,因为您可以继续安全地进行工作。请记住,您可以将Task
返回值存储在变量中,await
以后再存储在该变量中,即使使用相同的方法也是如此。例如,完成一堆其他工作后,一旦需要安全地访问传递的参数。同样,你也没有需要await
上Task
,当你运行它的权利。
无论如何,使传递的参数相对于线程安全的一种简单方法Task.Run
是:
你必须先装饰RunAsync
有async
:
private async void RunAsync()
重要的提示
如链接文档所述,最好标记的方法不应返回void。常见的例外是事件处理程序,例如单击按钮等。他们必须返回无效。否则,在使用时,我总是尝试返回a或。出于很多原因,这是一个好习惯。async
Task
Task<TResult>
async
现在,您可以await
运行Task
以下内容。您不能使用await
没有async
。
await Task.Run(() => MethodWithParameter(param));
因此,通常来说,如果您执行await
此任务,则可以避免将传入的参数视为潜在的共享资源,而同时又有一次修改多个线程中的内容的所有陷阱。另外,当心闭包。我不会深入介绍这些内容,但是链接的文章对此做得很好。
边注
主题不多,但是请小心在WinForms GUI线程上使用任何类型的“阻止”,因为它用标记了[STAThread]
。使用await
完全不会阻止,但我有时确实看到它与某种阻止结合使用。
“ Block”用引号引起来,因为从技术上讲您不能阻止WinForms GUI线程。是的,如果你使用lock
上的WinForms GUI线程它会仍然抽取消息,尽管你认为它的“封杀”。不是。
在极少数情况下,这可能导致奇怪的问题。lock
例如,您永远不想在绘画时使用的原因之一。但这是一个边缘且复杂的案例。但是我已经看到它会引起疯狂的问题。因此,出于完整性考虑,我将其记录下来。