1

実行したい長時間実行されているタスクがあり、そのステータス/進行状況をユーザー インターフェイスに通知できるとします。ここでの問題は、必要な UI がモーダル ダイアログであり、タスクを開始する前にそれを表示することも、タスクを開始してから表示することもできないことです。

試行 1: 最初にダイアログを表示してから、タスクを開始します。

ProgressDialog dlg = new ProgressDialog();
Task longRunningTask = CreateTask();  
dlg.ShowDialog();
longRunningTask.Start();
Task.WaitAll(longRunningTask);

これは明らかに機能しません。スレッドは ShowDialog() でブロックされ、タスクは開始されません。

試行 2: タスクを開始してからダイアログを表示:

ProgressDialog dlg = new ProgressDialog();
Task longRunningTask = CreateTask();  
longRunningTask.Start();
dlg.ShowDialog();
Task.WaitAll(longRunningTask);

しかし、このシナリオでは、タスクからの最初の進捗イベントを見逃す危険があります。さらに悪いことに、最初のイベントが作成中に進捗ダイアログに到着するため、"InvokeRequired" が false になったときに恐ろしいクロススレッド例外が発生します。まだ表示されていないため、ハンドルはありません。

タスクをダイアログに渡して、ダイアログにタスクを開始させることができると思いますが、それを必要としないこの問題に対するエレガントな解決策があるように感じますか?

4

1 に答える 1

3

イベントは、この問題を解決するのShownに最適です。

ProgressDialog dlg = new ProgressDialog();
dlg.Shown += (_, args) =>
{
    CreateTask().Start();
};
dlg.ShowDialog();

次に進む前にタスクが完了していることを確認する必要があり、完了する前にフォームが閉じられる可能性がある場合は、次のようにタスクを待機するように変更できます。

ProgressDialog dlg = new ProgressDialog();
Task longRunningTask = CreateTask();
dlg.Shown += (_, args) =>
{
    longRunningTask.Start();
};
dlg.ShowDialog();
longRunningTask.Wait();

どちらの場合も、タスクが作成される前にダイアログ フォームが作成されるため、dlgインスタンスをCreateTaskif に渡して、フォームのインスタンスへのアクセスを許可できることに注意してください。

于 2013-02-05T19:54:58.510 に答える