@ Рид предоставил элегантное решение , если вам нужно дождаться нескольких потоков.
Возможно, вы не захотите использовать Monitor
для этого.
Как указывало @ Reed , достаточно было бы событие, которое обеспечило бы самое чистое и понятное решение, соответствующее требованиям вашего кода.
Затраты на использование реальных примитивов синхронизации операционной системы, скорее всего, не будут иметь значения в вашем случае, например, при использовании, например, Monitor
даст только убывающую отдачу за счет гораздо более высокой сложности.
С учетом сказанного, вот реализация, использующая Monitor
и сигнализацию.
Вы можете использовать флаг bool
- защищенный замком - чтобы указать, что вы закончили и избежать ожидания в этом случае. (А)
Если вы действительно начинаете новую тему в Function2()
, где комментарии указывают и используют lock()
вокруг и WaitOne()
, и Release()
, то флаг вам вообще не нужен. (В)
A, используя флаг:
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, начало потока с 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());
}
}