子线程如何等待主线程中的某事完成?
How can a child thread wait for something in the main thread to complete?
通常问题是主线程等待子线程,我可以在 Task
上使用 await
。
但我有一种情况,子线程必须等待主线程中的某些方法完成才能继续。如何让这种沟通成为可能?
public void MainThread()
{
Task t = Task.Run(ChildThread); //not using await because we want to continue doing work that must be only on the main thread
WorkA();
WorkB();
???
WorkC();
}
public async Task ChildThread()
{
WorkD();
???
Need_WorkB_ToBeCompletedBeforeThisOne();
}
WorkA
WorkB
WorkC
都是主线程所必需的。在我的真实代码中,所有这些都是从子线程间接发出的,因为子线程需要完成它们但由于线程限制而无法完成。
我有办法让我的子线程告诉主线程已经开始工作(所以我将代码简化为您在此处看到的内容,任务一开始工作就会立即跟进)但我需要一些方法让发行者(子线程)了解这些命令的进度。
PS。感谢这个线程的回答,我为 Unity 创建了 CoroutineHost
,你可以 await
yield IEnumerator
方法,你可以从你的任何子线程发出到你的主线程来完成: https://github.com/5argon/E7Unity/tree/master/CoroutineHost
如果 WorkB 是一个任务,我会想象这样的事情:
public void MainThread()
{
Task workB = WorkB();
ChildThread(workB); // you don't need to use Task.Run here, the task is ran automatically
WorkA();
WorkC();
}
public async Task ChildThread(Task otherTaskToWait)
{
WorkD();
await otherTaskToWait;
Need_WorkB_ToBeCompletedBeforeThisOne();
}
您正在寻找 "signal"。由于 child 是异步的并且信号仅使用一次,因此 TaskCompletionSource<T>
可以很好地工作:
public void MainThread()
{
var tcs = new TaskCompletionSource<object>(); // Create the signal
Task t = Task.Run(() => ChildThread(tcs.Task)); // Pass the "receiver" end to ChildThread
WorkA();
WorkB();
tcs.SetResult(null); // Send the signal
WorkC();
}
public async Task ChildThread(Task workBCompleted)
{
WorkD();
await workBCompleted; // (asynchronously) wait for the signal to be sent
Need_WorkB_ToBeCompletedBeforeThisOne();
}
参见 my book for more information. If you need a "signal" that can become set and unset multiple times, then you should use AsyncManualResetEvent
中的技巧 11.4 "Async Signals"。
通常问题是主线程等待子线程,我可以在 Task
上使用 await
。
但我有一种情况,子线程必须等待主线程中的某些方法完成才能继续。如何让这种沟通成为可能?
public void MainThread()
{
Task t = Task.Run(ChildThread); //not using await because we want to continue doing work that must be only on the main thread
WorkA();
WorkB();
???
WorkC();
}
public async Task ChildThread()
{
WorkD();
???
Need_WorkB_ToBeCompletedBeforeThisOne();
}
WorkA
WorkB
WorkC
都是主线程所必需的。在我的真实代码中,所有这些都是从子线程间接发出的,因为子线程需要完成它们但由于线程限制而无法完成。
我有办法让我的子线程告诉主线程已经开始工作(所以我将代码简化为您在此处看到的内容,任务一开始工作就会立即跟进)但我需要一些方法让发行者(子线程)了解这些命令的进度。
PS。感谢这个线程的回答,我为 Unity 创建了 CoroutineHost
,你可以 await
yield IEnumerator
方法,你可以从你的任何子线程发出到你的主线程来完成: https://github.com/5argon/E7Unity/tree/master/CoroutineHost
如果 WorkB 是一个任务,我会想象这样的事情:
public void MainThread()
{
Task workB = WorkB();
ChildThread(workB); // you don't need to use Task.Run here, the task is ran automatically
WorkA();
WorkC();
}
public async Task ChildThread(Task otherTaskToWait)
{
WorkD();
await otherTaskToWait;
Need_WorkB_ToBeCompletedBeforeThisOne();
}
您正在寻找 "signal"。由于 child 是异步的并且信号仅使用一次,因此 TaskCompletionSource<T>
可以很好地工作:
public void MainThread()
{
var tcs = new TaskCompletionSource<object>(); // Create the signal
Task t = Task.Run(() => ChildThread(tcs.Task)); // Pass the "receiver" end to ChildThread
WorkA();
WorkB();
tcs.SetResult(null); // Send the signal
WorkC();
}
public async Task ChildThread(Task workBCompleted)
{
WorkD();
await workBCompleted; // (asynchronously) wait for the signal to be sent
Need_WorkB_ToBeCompletedBeforeThisOne();
}
参见 my book for more information. If you need a "signal" that can become set and unset multiple times, then you should use AsyncManualResetEvent
中的技巧 11.4 "Async Signals"。