@Reed provided an elegant solution if you need to wait for multiple threads.
You might not want to use Monitor
fro this.
As @Reed pointed out, an event would suffice and would provide the cleanest and most understandable solution that matches the requirements of your code.
The overhead of using real operating system sync primitives will most probably not matter in your case and using e.g. Monitor
would provide only diminishing returns at the cost of much higher complexity.
With that said, here is an implementation using Monitor
and signaling.
You can use a bool
flag - guarded by the lock - to indicate that you have finished and avoid waiting in that case. (A)
If you really start a new thread within Function2()
where the comments indicate and use lock()
around both WaitOne()
and Release()
, you do not need the flag at all. (B)
A, using a flag:
class Program
{
static object syncRoot = new object();
//lock implies a membar, no need for volatile here.
static bool finished = false;
static byte b;
public static byte Function1()
{
lock (syncRoot)
{
//Wait only if F2 has not finished yet.
if (!finished)
{
Monitor.Wait(syncRoot);
}
}
return b;
}
static public void Function2()
{
// do some thing
b = 1;
lock (syncRoot)
{
finished = true;
Monitor.Pulse(syncRoot);
}
}
static void Main(string[] args)
{
new Thread(Function2).Start();
Console.WriteLine(Function1());
}
}
B, starting a thread from Function1
:
class Program
{
static object syncRoot = new object();
static byte b;
public static byte Function1()
{
lock (syncRoot)
{
// new thread starting in Function2;
new Thread(Function2).Start();
Monitor.Wait(syncRoot);
}
return b;
}
static public void Function2()
{
// do some thing
b = 1;
//We need to take the lock here as well
lock (syncRoot)
{
Monitor.Pulse(syncRoot);
}
}
static void Main(string[] args)
{
Console.WriteLine(Function1());
}
}