子线程如何等待主线程中的某些内容完成?

时间:2017-08-16 13:14:06

标签: c# multithreading task-parallel-library

通常问题是主线程等待子线程,我可以在await上使用Task

但我有一种情况,子线程必须等待主线程中的某些方法完成才能继续。如何使这种沟通成为可能?

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

2 个答案:

答案 0 :(得分:4)

你正在寻找一个“信号”。由于子节点是异步的,并且信号只使用一次,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中的食谱11.4“异步信号”。如果您需要多次设置和取消设置的“信号”,则应使用AsyncManualResetEvent

答案 1 :(得分:1)

如果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();
}