C# 子线程如何等待主线程中的某些内容完成?
通常问题是主线程等待子线程,我可以在C# 子线程如何等待主线程中的某些内容完成?,c#,multithreading,task-parallel-library,C#,Multithreading,Task Parallel Library,通常问题是主线程等待子线程,我可以在任务上使用wait 但是我有一种情况,子线程必须等待主线程中的某个方法完成后才能继续。如何使这种交流成为可能 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(); Wor
任务上使用wait
但是我有一种情况,子线程必须等待主线程中的某个方法完成后才能继续。如何使这种交流成为可能
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
都必须位于主线程上。在我的实际代码中,所有这些问题都是从子线程间接发出的,因为子线程需要完成它们,但由于线程限制而无法完成
我有一种方法让我的子线程告诉主线程已经开始工作了(因此我将代码简化为您在这里看到的,只要任务开始,工作就会立即进行),但是我需要一些方法让发布者(子线程)知道这些命令的进度
另外,由于这个线程的回答,我为Unity创建了CoroutineHost
,您可以等待从您的任何子线程向您的主线程发出的yield IEnumerator
方法:如果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();
}
如果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();
}
你在寻找一个“信号”。由于子级是异步的,并且信号只使用一次,因此TaskCompletionSource
可以很好地工作:
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();
}
public void主线程()
{
var tcs=new TaskCompletionSource();//创建信号
Task t=Task.Run(()=>ChildThread(tcs.Task));//将“receiver”端传递给ChildThread
WorkA();
WorkB();
SetResult(null);//发送信号
WorkC();
}
公共异步任务子线程(任务工作已完成)
{
WorkD();
等待工作完成;//(异步)等待发送信号
需要在此之前完成工作();
}
有关更多信息,请参阅中的配方11.4“异步信号”。如果您需要一个可以多次设置和取消设置的“信号”,那么您应该使用。您正在寻找一个“信号”。由于子级是异步的,并且信号只使用一次,因此TaskCompletionSource
可以很好地工作:
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();
}
public void主线程()
{
var tcs=new TaskCompletionSource();//创建信号
Task t=Task.Run(()=>ChildThread(tcs.Task));//将“receiver”端传递给ChildThread
WorkA();
WorkB();
SetResult(null);//发送信号
WorkC();
}
公共异步任务子线程(任务工作已完成)
{
WorkD();
等待工作完成;//(异步)等待发送信号
需要在此之前完成工作();
}
有关更多信息,请参阅中的配方11.4“异步信号”。如果您需要一个可以多次设置和取消设置的“信号”,那么您应该使用。为什么不让ChildThread()
只执行WorkD()
并返回,然后在MainThread()
中调用need\u WorkB…()
?我的错,实际上,WorkA到C将由ChildThread()
发出(因为如果WorkA到C是在主线程以外的线程上执行的,则存在软件限制)。我需要一种方法,以便在发出后,ChildThread()
可以获得主线程中情况的某种指示。为什么不使用ChildThread())
只做WorkD()
并返回,然后在MainThread()
中等待WorkB()
并调用Need\u WorkB…()
之后?我糟糕的,实际上WorkA到C将由ChildThread()
(因为如果WorkA到C是在主线程以外的线程上执行的,则存在软件限制)我想要一种方法,以便在问题发生后,ChildThread()
可以获得主线程中运行情况的某种指示。谢谢,但是由于程序的限制,WorkB
不能在另一个线程上(Unity)。如果WorkB
确实通过Task WorkB=WorkB();
成为了一项任务,那就意味着我们已经把它放在了另一个线程中了?(因此我们可以等待它)@5.如果您使用的是Unity,那么您使用的是2017年的实验版本吗?否则,Unity不知道Task。我假设workb可以在不同的平台上运行thread@5argon一个操作是异步的这一事实并不意味着它正在使用另一个线程。在另一个线程中运行代码只是使操作异步的一种方法非同步的。@5argon不管现在有什么问题,我建议您等待,因为我发现Unity将来可能会允许UnityWebRequest在不同的线程上运行(否则,为什么还要允许不同的线程…?)斯蒂芬·克利里的答案正是你想要的。哦,我刚在年读到关于随意手动创建你自己的任务,意识到这实际上是斯蒂芬·克利里的答案。我想现在没事了。(有了这个,实际上这个答案几乎等于Stephen的答案,通过使WorkB
的内部产生TaskCompletionSource
->Task
)谢谢,但是WorkB
由于程序的限制不能在另一个线程上(Unity)。如果WorkB
确实通过Task WorkB=WorkB();
成为了一项任务,那就意味着我们已经把它放在了另一个线程中了?(因此我们可以等待它)@5.如果您使用的是Unity,那么您使用的是2017年的实验版本吗?否则,Unity不知道Task。我假设workb可以在不同的平台上运行thread@5argon一个操作是异步的这一事实并不意味着它正在使用另一个线程。在另一个线程中运行代码只是使操作异步的一种方法非同步的。@5argon不管现在有什么问题,我建议您等待,因为我发现Unity将来可能会允许UnityWebRequest在不同的线程上运行(否则,为什么还要允许