複数のスレッドを待つ必要がある場合、@Reed はエレガントなソリューションを提供しました。
これを使用したくない場合がありますMonitor
。@Reedが指摘したように、イベントは十分であり、コードの要件に一致する最もクリーンで最も理解しやすいソリューションを提供します。
実際のオペレーティングシステムの同期プリミティブを使用するオーバーヘッドは、おそらくあなたのケースでは問題にならないでしょう.egを使用してもMonitor
、はるかに複雑になるという犠牲を払って利益が減少するだけです。
そうは言っても、これはMonitor
シグナリングを使用した実装です。
ロックで保護されたフラグを使用しbool
て、終了したことを示し、その場合の待機を回避できます。(A)コメントが示す場所
内で新しいスレッドを実際に開始し、と の両方を使用する場合、フラグはまったく必要ありません。(ロ)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());
}
}