多数のtime\CPU集約型プロセス(TimeExpensiveタイプ)を次々に実行しています。メインスレッド(A)は、別のスレッド(B)でTimeExpensiveプロセスを非同期的に開始し、非アクティブになります。完了時に、スレッドBは呼び出し元の完了ハンドラーを同期的に起動し、スレッドBで次のTimeExpensiveプロセスを開始します。新しいスレッド(C)が作成されますが、Cの開始後、Bは終了します。したがって、n個のプロセスの場合、n個のスレッドが作成され、ほとんどの場合、それらは共存しません。
線形シングルスレッド方式での実装を希望する場合もありますが、TimeExpensiveはサードパーティによって実装されており、実行中はすべてのシステムコアを使用し、数時間実行されます。
//This will run as console app
class Program
{
static void Main(string[] args)
{
new Program().StartJobs();
}
void StartJobs()
{
Main mainJob = new Main();
mainJob.MainCompletionEvent +=
new Action<object, EventArgs>(mainJob_MainCompletionEvent);
mainJob.Start();
}
void mainJob_MainCompletionEvent(object sender, EventArgs e)
{
//if(success) Environment.Exit(0);
}
}
class Main
{
int processCounter = 0;
public event Action<object, EventArgs> MainCompletionEvent;
public void Start()
{
//...do other important tasks here...
processCounter++;
TimeExpensive te = new TimeExpensive();
te.CompletionEvent += new Action(TimeExpensive_CompletionHandler);
Thread aThread = new Thread(te.Run);
aThread.IsBackground = false;
aThread.Name = "TimeExpensive Thread: " + processCounter;
aThread.Start();
}
void TimeExpensive_CompletionHandler()
{
Console.WriteLine("current Thread Name: " + Thread.CurrentThread.Name);
//Start another Process In Background if
if (processCounter < 5)
{
Start();
}
else
{
Console.ReadKey();
if (JobCompletionEvent != null)
JobCompletionEvent(this, new EventArgs());
}
}
}
class TimeExpensive
{
public event Action CompletionEvent;
public void Run()
{
//doing time expensive task
//...
//when finish Notify completion Handler...
if (CompletionEvent != null)
{
CompletionEvent();
}
}
}
//Output
current Thread Name: TimeExpensive Thread: 1
current Thread Name: TimeExpensive Thread: 2
current Thread Name: TimeExpensive Thread: 3
current Thread Name: TimeExpensive Thread: 4
current Thread Name: TimeExpensive Thread: 5
上記の実装は、私が説明した動作を模倣しています。私を悩ませているのは、次のスレッドが開始するまで同期的に実行されているイベントハンドラーであり、この間、設計されていない多くのタスクを実行しています。
これが適切かどうかわからない場合、スレッドBの完了ハンドラーにいる間にスレッドAに戻る方法はありますか?または、別のデリゲートを使用してイベントハンドラーの実行を開始する方がよいでしょうか。BeginInvoke?
シンプルでありながら安全なアプローチでやりたいです。どんな助けでも大歓迎です。
PS私はたくさんの投稿を読みましたが、誰もこのシナリオをうまく扱っていませんでした。
編集
コンソールアプリでこのコードをキックスタートする方法を示すために、静的メインが追加されました。「メイン」ジョブを開始するためのUIを作成することもできることを忘れないでください。mainJobオブジェクトを作成して実行するためのBackgroundWorkerスレッドを確実に作成します。ありがとう!