1

再入可能性の問題があり、UIを保持しないようにする別の方法が常にあるため、Application.DoEventsには近づきません。私は長い間、マルチスレッドの単純な代替手段として、Application.Idleイベントでバックグラウンド作業を行うことを好みました。ただし、長時間実行されるタスクの場合、DoEventsループを使用してApplication.Idleで操作を実行することは許容されますか?

class LongRunningTask : IDisposable {

    public LongRunningTask(IEnumerable<Tidbit> listOfDataToBeProcessed) {
       Application.Idle += OnIdle;
    
        foreach(Tidbit t in listofDataToBeProcessed) {
            tidbits.Enqueue(t);
        }
    }
    
    // Small pieces of data to process
    Queue<Tidbit> tidbits = new Queue<Tidbit>();
    
    void OnIdle(object sender, EventArgs e) {
        while(tidbits.Count > 0) {
            var tidbit = tasks.Dequeue();
            tidbit.Process();
            // Process any messages that have queued up
            // while the data was being processed
            Application.DoEvents();
        }
    }
    
    public void Dispose() {
        Application.Idle -= OnIdle;
    }
}

ここでのロジックは、DoEventsを呼び出すApplication.Idleイベントでは、キューに入れられたメッセージがないため、コードを再入力できないようにする必要があるということです。各tidbitは、メッセージキュー(またはUI)を大幅に保持しないように十分に高速に処理されます。

それで、このアプローチに害や欠点はありますか?つまり、アイドルイベントでDoEventsを呼び出すのは安全ですか?C#5にこの種の状況に対処する機能があることは知っていますが、 C#5を使用していない人(現時点ではほとんどの人)にとって、そして一般的な好奇心から、これは良いことです予定?または、マルチスレッドに頼らずに、長時間実行される操作中にメッセージを処理するためのより簡単な代替手段はありますか?

これが魔法の弾丸だとは思わないでください。非同期アプローチと同じ落とし穴があることを私は知っています。私は、彼のアプリケーションを一貫した状態に保つことができなければならないことを認識しています。そして、私マルチスレッドソリューションがあることを知っています。私はそれらを避けています。なんで?マルチスレッドはもっと複雑だからです。それは非現実的だとは思いません。

4

1 に答える 1

1

ここで行っていることは、協調的マルチタスキングによく似ています。興味深いアイデアですが、このような場合はマルチスレッドを使用する必要があります。Task.Factory.StartNew().NET には、TPL ライブラリなどの多くのヘルパー システムがあり、これにより、.NET を非常に簡単に実行できます。

私はそれに反対することをお勧めします。

ただし、明確にするために、私には明確な理由はありません。プログラミングに関する多くの分野と同様に、機能する場合は機能します。ただし、混合してはいけないもの、特にバックグラウンド タスクと UI タスクを混合しています。バックグラウンド タスクを分離して、マルチ スレッド、スレッド プール、バックグラウンド タスク、および TPL を使い始めると、それが機能し、長期的には生活が楽になることがすぐにわかると思います。

于 2010-11-07T17:21:44.970 に答える