Stackoverflowに投稿されている例の1つを使用して、バックグラウンドワーカーをテストするためのサンプルコンソールアプリケーションを作成しました。 mainメソッドで始まるbackgroundworkerがありますが、mainメソッドでconsole.readkeyを記述したため、Enterキーを押すと、操作の途中で終了します。しかし、私はバックグラウンドワーカーが仕事を終えてアプリケーションを終了するまでそれを待ってもらいたいです。これは私のコードです。
class Program
{
private static BackgroundWorker worker = new BackgroundWorker();
private event EventHandler BackgroundWorkFinished;
static void Main(string[] args)
{
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.ProgressChanged += worker_ProgressChanged;
worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = true;
Console.WriteLine("Starting Application...");
worker.RunWorkerAsync();
Console.ReadKey();
}
static void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
Console.WriteLine(e.ProgressPercentage.ToString());
}
static void worker_DoWork(object sender, DoWorkEventArgs e)
{
Console.WriteLine("Starting to do some work now...");
int i;
for (i = 1; i < 10; i++)
{
Thread.Sleep(1000);
worker.ReportProgress(Convert.ToInt32((100.0 * i) / 10));
}
e.Result = i;
}
static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Console.WriteLine("Value Of i = " + e.Result.ToString());
Console.WriteLine("Done now...");
}
}
BackgroundWorkerとメインスレッド間の通信方法については、 BackgroundWorkerがキャンセルされるのを待つ方法 投稿を参照してください。
基本的に、DoWorkの終了時に設定したイベントを使用して、DoWorkが完了したことを通知する必要があります。次に、メインスレッドのそのイベントでWaitOne()を実行します。
Bgwの主な目的は、Windows MessageQueueと対話することです。つまり、WinFormsおよびWPFアプリケーションで最も役立ちます。
コンソールアプリケーションは、Bgwを使用またはテストするのに適切な場所ではありません。奇妙な結果が得られます。重要なポイントでManagedThreadIdを出力して、何が起こるかを確認します。
そして、いくつかの標準的なアドバイス:worker_RunWorkerCompleted()
はe.Error
をチェックする必要があります。 現時点では、空のcatch{}
ブロックがあるのと同じです。
処理がより複雑なe.Result
を読み取ると、DoWorkからのエラーがスローされるようになりました。
これは私が今やったことです。しかし、console.readkey()
は機能していません。アプリケーションはReadKey()
関数を待機していません。
_class Program
{
private static BackgroundWorker worker = new System.ComponentModel.BackgroundWorker();
private static AutoResetEvent resetEvent = new AutoResetEvent(false);
static void Main(string[] args)
{
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.ProgressChanged += worker_ProgressChanged;
worker.WorkerReportsProgress = true;
Console.WriteLine("Starting Application...");
worker.RunWorkerAsync();
resetEvent.WaitOne();
Console.ReadKey();
}
static void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
Console.WriteLine(e.ProgressPercentage.ToString());
}
static void worker_DoWork(object sender, DoWorkEventArgs e)
{
Console.WriteLine("Starting to do some work now...");
int i;
for (i = 1; i < 10; i++)
{
Thread.Sleep(1000);
worker.ReportProgress(Convert.ToInt32((100.0 * i) / 10));
}
e.Result = i;
resetEvent.Set();
}
static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Console.WriteLine("Value Of i = " + e.Result.ToString());
Console.WriteLine("Done now...");
}
}
_
修正の編集:resetEvent.Set()
をRunWorkerCompletedではなく、内部DoWorkに移動しました。メインスレッドがイベントを待機しているため、Completedイベントハンドラーは呼び出されません。