1

いくつかのコードでこれを見ましたが、私には意味がありませんでした。

Form_Load イベントで次のように使用されます。

    BackgroundWorker asyncWorker = new BackgroundWorker();
    asyncWorker.DoWork += new DoWorkEventHandler(AsynchDoWork);
    asyncWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(AsynchCompleted);
    asyncWorker.RunWorkerAsync();

   // a for each loop that can take some time to populate a combobx on the form

また、同じ目標を達成するためのより良い代替手段はありますか? バックグラウンドワーカー以外?

4

4 に答える 4

2

これにはTask Parallell Library を使用します。チュートリアルに適しているのはTask Parallel Library: 1 of nです。バックグラウンド タスクの結果に従ってコンボ ボックスを更新するには、次のようにします。

// Get UI scheduler. Use this to update ui thread in continuation.
TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();

// You can use TPL like this...
List<object> objList = new List<object>();
Task<object[]> task = Task.Factory.StartNew<object[]>(() =>
    {
        // Pull all your data into some object.
        object[] objArr = new object[] { "Some", "Stuff", "..." };
        return objArr;
    }, TaskCreationOptions.PreferFairness);

// Continuation firs after the antecedent task is completed.
task.ContinueWith(ant =>
    {
        // Get returned data set.
        object[] resultSet = (task.Result as object[]);

        // Check task status.
        switch (task.Status)
        {
            // Handle any exceptions to prevent UnobservedTaskException.             
            case TaskStatus.RanToCompletion:
                if (task.Result != null)
                {
                    // Update UI comboBox.
                }
                break;
            default:
                break;
        }
    }, CancellationToken.None, TaskContinuationOptions.None, uiScheduler);

ここではuiScheduler、継続デリゲート内から ui スレッドを更新できます。継続デリゲートは、継続元タスクが (正常に完了したかどうかに関係なく) 完了したときに起動します。

この場合、継続は例外ハンドラーとしても機能しAggregateExceptions、バックグラウンド スレッドからスローされる可能性があるものをキャッチします。

これが役立つことを願っています。

于 2012-09-11T15:29:11.463 に答える
2

私が正しく理解している場合、実際に求めているのはCombobox、バックグラウンド スレッドまたは UI スレッドから値を入力する必要があるかどうかです。

に入力するのに時間がかかる理由がCombobox、アイテムを実際に取得するのに時間がかかるためである場合 (たとえば、データベースからアイテムを取得する場合)、おそらくこの作業を でBackgroundWorker行い、次に追加するだけにする必要があります。取得したアイテムをComboboxイベントにRunWorkerCompleted

このRunWorkerCompletedイベントは、バックグラウンド スレッドから引き続き実行されInvokeますが、UI 要素へのすべてのアクセスに対して内部で自動的に呼び出されるため、UI 要素の更新に問題はありません。

もちろん、長時間実行する lop は、コード例のように、への呼び出しと同じコード ブロックではなく、イベントで実行する必要があります。DoWorkRunWorkerAsync

逆に、すぐに入手できる非常に大量のアイテムについて話しているだけAddRangeで、その量のために の呼び出しに時間がかかる場合は、バックグラウンド スレッドからこれを呼び出すことはできません。 UI スレッド。

于 2012-09-11T15:14:21.427 に答える
1

スコープについてはわかりません。クラスのメンバーとして BackgroundWorker を作成します。

BackgroundWorker は UI スレッドから作業を取り除き、更新の進行状況に簡単にアクセスできるメソッドを備えています。

代替案に関しては、それはあなたの目標が正確に何であるかによって異なります. UI を更新しない小さなタスクの場合は、System.Threading.ThreadPool を使用できます。

于 2012-09-11T15:14:07.563 に答える
1

「また、同じ目標を達成するためのより良い代替手段はありますか?バックグラウンドワーカー以外に?」という質問に答えるために。

いいえ。これは、winform の実行時間の長いブロッキング タスクを処理する最も簡単な方法です。他の方法 (BeginInvoke) もありますが、バックグラウンド ワーカーを使用する方がはるかに簡単です。

于 2012-09-11T15:14:22.643 に答える