2

私は私の現在の状況に対する非常に単純な解決策のように見えるものを見つけました。

私の現在の状況では、GUIスレッドを停止させないように、新しいスレッドでI/Oを多用する操作を実行したいと考えています。フォームのメンバーとして、これらのI / O操作をすでに実行する関数を作成しましたが、GUIスレッドで実行すると、アプリケーションを使用するのが非常に面倒になります。したがって、私の計画は、この関数を新しいスレッドで実行することでした。そこで、自分のフォームでThread変数を作成し、その関数をThreadStartパラメーターとして使用できるようにしようとしています。しかし、それは気に入らないようです。

別のスレッドへの応答として、ここでエレガントなソリューションを見つけました。

///...blah blah updating files
string newText = "abc"; // running on worker thread
this.Invoke((MethodInvoker)delegate {
    someLabel.Text = newText; // runs on UI thread
});
///...blah blah more updating files

その応答の外観から、この関数を新しいスレッドで実行し、匿名関数を使用して、スレッドが計算を終了したときにフォームを更新することができます。しかし、私はその回答の空白を埋めるのに十分ではありません。

私がスレッドについて読んだように見えることはすべて、私のThreadStart関数は新しいクラスの静的メソッドである必要があると言っています。その応答は、Formクラス内でそれを実行できることを示唆しているようです。そのため、this参照は引き続きFormインスタンスを参照します。そうでなければ、ThreadStartパラメーターが別のクラスである場合、Formインスタンスへの参照を渡す必要があり、それはより多くのコードのように見えますよね?

誰かが私がその応答のコンテキストを記入するのを手伝ってくれませんか?前もって感謝します!

4

1 に答える 1

1

これを行う方法はたくさんあります。多くのバージョンで使用されてきた非常に単純でわかりやすい方法は、BackgroundWorkerを使用することです。まさにこの場合のために設計されています。DoWorkバックグラウンドスレッドで実行されるメソッドと、CompletedUIスレッドで実行される作業の完了後に発生するイベントがあります(したがって、UIを結果で更新するためにinvokeなどを呼び出す必要はありません)。進行状況のレポートのサポートも組み込まれているため(レポートの進行状況イベントはUIスレッドでも実行されます)、進行状況バーまたはステータステキストを簡単に更新できます。

MSDNにもいくつかのがあり、いくつかの簡単な検索でさらに多くの例を見つけることができます。

C#4.0で利用できるようになったもう1つのオプションは、を使用することTasksです。バックグラウンドスレッドで実行される新しいタスクを開始してから、UIスレッドで実行される継続を追加できます。

簡単な例を次に示します。

private void button1_Click(object sender, EventArgs e)
{
    Task.Factory.StartNew(() => doStuffInBackground())
        .ContinueWith(task => updateUI(), TaskScheduler.FromCurrentSynchronizationContext());
}

private void updateUI()
{
    throw new NotImplementedException();
}

private void doStuffInBackground()
{
    throw new NotImplementedException();
}

もちろん、私が持っている実際のラムダでやりたいことは何でもできます。あるいは、署名が正しいことを確認する限り、ラムダを削除してメソッドを直接そこに置くこともできます。必要に応じて、これらの継続をチェーンし続けることもできます。たとえば、タスク1、ラベルの更新、タスク2、ラベルの更新などが可能です。主な欠点は、プログレスバーの更新が苦手なことです。多くの場合、ループの内側にありますBackgroundWorker

于 2012-07-24T16:34:07.913 に答える