2

いくつかのBackgroundWorker要素を使用して、バックグラウンドで処理を行う単純な Windows フォーム アプリがあります。開発中に.Text、メソッドで Label の値を取得および設定するDoWork()ことはできるが、DrowDownList の値を取得できないことに気付きました。

BackgroundWorker は UI インタラクションを持たないという印象を受けましたが、このルールに例外はありますか?

BackgroundWorker から UI を更新するための提案を探しているわけではありません。BackgroundWorker から直接 ToolStripStatusLabel のテキストを更新するなど、実行できるショートカットがあるかどうかに興味があります。

以下は単純な例です。ワーカー 1 は UI を直接更新し、ワーカー 2 は進行状況の更新を使用します。

private void button1_Click(object sender, EventArgs e)
{
    backgroundWorker1.RunWorkerAsync();
}

private void button2_Click(object sender, EventArgs e)
{
    backgroundWorker2.RunWorkerAsync();
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    toolStripStatusLabel1.Text = "Performing task 1...";
    performTaskOne();
    toolStripStatusLabel1.Text = "Task 1 done.";

    toolStripStatusLabel1.Text = "Performing task 2...";
    performTaskTwo();
    toolStripStatusLabel1.Text = "Task 2 done.";

    toolStripStatusLabel1.Text = "Performing task 3...";
    performTaskThree();
    toolStripStatusLabel1.Text = "Task 3 done.";
}

private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
{
    backgroundWorker2.ReportProgress(0, "Performing task 1...");
    performTaskOne();
    backgroundWorker2.ReportProgress(20, "Task 1 done.");

    backgroundWorker2.ReportProgress(40, "Performing task 2...");
    performTaskTwo();
    backgroundWorker2.ReportProgress(60, "Task 2 done.");

    backgroundWorker2.ReportProgress(80, "Performing task 3...");
    performTaskThree();
    backgroundWorker2.ReportProgress(100, "Task 3 done.");
}

private void backgroundWorker2_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    string status = (string)e.UserState;
    toolStripStatusLabel1.Text = status;
}

private void performTaskThree()
{
    Thread.Sleep(1000);
}

private void performTaskTwo()
{
    Thread.Sleep(1000);
}

private void performTaskOne()
{
    Thread.Sleep(1000);
}
4

1 に答える 1

0

バックグラウンド スレッドから UI にアクセスしたり更新したりしないでください。限目。

これはほとんどの UI 要素の機能であり、UI スレッドからアクセスされていないかどうかを検出し、積極的に例外をスローするため、開発者はコードを初めて実行したときに、コントロールに不適切にアクセスしていることをすぐに認識できます。

すべての UI コントロール、および UI コントロールのすべての側面にこの機能があるわけではありません。特定のメンバーは、UI 以外のスレッドから安全に使用できるオブジェクトのメンバーとして明確に文書化されています (たとえば、Invokeコントロールのメソッドは非 UI スレッドから使​​用できることは明らかです。それが存在する理由です)。そのように文書化されていないものについては、非 UI スレッドで使用しないでください。

初めて使用するときにクラッシュしないからといって、それが機能するとは限りません。つまり、他のどのスレッドが同時に共有リソースにアクセスしているかに応じて、コード全体に競合状態が発生する可能性があります。テストすればうまくいくかもしれませんし、繰り返しうまくいくかもしれません。おそらく、プログラムがクラッシュしたり、データが破損したり、単に機能しなくなったり、あらゆる種類の奇妙で厄介なことが発生したりするでしょう。そのようなコードがクライアントに送信された場合、突然、さまざまな人々がさまざまな予想外の方法でコードを実行し、非常にさまざまな種類の環境でコードを実行するようになると、

そのため、時間をかけて UI スレッドからのみ UI コントロールにアクセスするようにしてください。

また、まったく別の注意として、UI とプレゼンテーション ロジックをビジネス ロジックから分離するようにコードを整理すると、非常に役立つことにも注意してください。それらを混在させると、推論、理解、保守、または変更が困難なアプリケーションになります。

于 2013-06-13T20:11:38.757 に答える