5argon 5argon - 1 year ago 66
C# Question

How can a child thread wait for something in the main thread to complete?

Usually the question is for the main thread to wait for child thread which I can use

await
on the
Task
.

But I have a situation where the child thread must wait for some method in the main thread to complete before continuing. How to make this communication possible?

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
are all necessary to be on the main thread. All of them would be issue indirectly from the child thread in my real code because child thread need them done but could not do it because of thread restriction.

I have a way for my child thread to tell main thread to do work already (so I simplify the code to what you see here, as soon as the task start the work will immediately follows) but I need some way for the issuer (child thread) to know about the progress of those commands.

PS. Thanks to answers from this thread I have created
CoroutineHost
for Unity, which you are able to
await
the
yield IEnumerator
method that you can issue to your main thread to do from any of your child threads : https://github.com/5argon/E7Unity/tree/master/CoroutineHost

Answer Source

You're looking for a "signal". Since the child is asynchronous and the signal is used only one time, a TaskCompletionSource<T> would work nicely:

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

See recipe 11.4 "Async Signals" in my book for more information. If you need a "signal" that can become set and unset multiple times, then you should use AsyncManualResetEvent.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download