2

時間のかかるタスクを実行するために、Backgroudworkerを使用していくつかの作業を行いました。

public void ConnectDataProvider()
    {
        bgw = new BackgroundWorker();
        bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
        bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);

    }

別の方法でバックグラウンドワーカーを開始します。

public void StartPolling()
    {
        bgw.RunWorkerAsync();
    }

次に、イベント処理を行いました。

void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // do it over again
        StartPolling();
    }    

void bgw_DoWork(object sender, DoWorkEventArgs e)
    {
        // do work
        WriteData();
    }

ご覧のとおり、完了時にワーカーを最初からやり直しました。これで、これは1人のバックグラウンドワーカーで機能します。

今、私はコレクションが欲しいです、そして各アイテムはこのタスクを実行するべきです。ただし、上記の概念では、ワーカーを最初からやり直すため、最初に開始したワーカーで実行を継続します。私は、タイマーを組み合わせることで状況を解決し、他のワーカースレッドに道を譲ることができるのではないかと考えています。

BackgroundWorkerはまだ良い選択ですか?私のようにBackgroundWorkerを再利用するのは一般的ですか?

編集1:明確にするために:私が直面している問題は、それぞれ独自のBackgroundWorkerを使用してコレクションを管理する必要があるということです。各アイテムから定期的にリクエストを出すタイマーを考えていました。これは私が立ち往生しているところです。

編集2:私自身の答えを見てください、私はこの問題を解決しませんでしたが、私が欲しいものを手に入れるためにタイマーと一緒に行くことができることがわかりました。

編集3:私が達成したかったことを明確にするために(別の試み、私はそれが得意ではありません):GPS追跡用の追跡オブジェクトがあります。私はそれらの全体を追跡したいので、追跡デバイスごとに1つのオブジェクト。それらはすべて頻繁にポーリングする必要があります。単一のテストオブジェクト用にBackgroundWorkerを設定しました。私は、Backgroundworkerが完了したときに教えてくれる方法が好きでした。しかし、すべての追跡オブジェクトで機能させることはできませんでした。

現在、すべての追跡オブジェクトには独自のタイマーがあります。このタイマーは新しいスレッドを生成し、時間のかかる作業を実行します(私はDoWriteと名付けました)。タイマーを破棄してから新しいタイマーを作成するため、BackgroundWorkerは必要ありません。それがすべてです。

4

6 に答える 6

4

これらはいくつありますか?コレクション内のアイテムとスレッドの間に 1 対 1 の関係を作成する場合は注意が必要です。別のコーダーがやって来て、このコレクションを計画以上に拡張する可能性があります。

このような場合、私は通常、1 つのスレッドと 1 つのキューのみを使用するのが好きです。そのため、イベントは、実行する必要がある作業を ConcurrentQueue に入れるだけで、実行されていない場合はスレッドが開始され、キューに入れられた作業が完了するまで処理されます。やることがなくなって死ぬ。次回イベントにさらに作業が発生すると、スレッドが実行されているかどうかがチェックされ、開始されます。

多くのことが起こっている場合、多くのスレッドを停止して開始するのではなく、1 つのスレッドだけを実行するか、ほとんど進行していない場合、1 つのスレッドはほとんど実行されないため、コストがかかりません。

于 2009-09-22T01:22:03.287 に答える
1

Dowork() に while() ループを配置するだけで、おそらく少し Sleep() を使用すると、ソリューションがより論理的に見えます。

また、複数の Bgw を実行することに異論はありませんが、速度が大幅に向上するわけではありません。

于 2009-08-18T08:18:05.793 に答える
1

progresschanged イベントを使用しないのはなぜですか? データを渡すために userstate オブジェクトを使用できます。

作業中はデバイスをプールするだけで、処理中に変更されたデータが UI スレッドに送信されます。

無限に実行し、キャンセルを使用してそのスレッドを停止します。

よろしく。

于 2009-09-21T16:11:40.390 に答える
1

説明したことを正確に行うことができます-関連するバックグラウンドワーカーへの参照を に渡すことを確認してくださいStartPolling

void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // do it over again
    StartPolling((BackgroundWorker)sender);
}

public void StartPolling(BackgroundWorker worker)
{
    worker.RunWorkerAsync();
}

それから明らかに、それに応じて のコレクションを管理する必要がありますBackgroundWorker

于 2009-08-18T09:14:03.997 に答える
0

複数の時間のかかるタスクを同時に実行する場合は、スレッド プールを使用することをお勧めします。

http://msdn.microsoft.com/en-us/library/ms973903.aspx

于 2009-08-18T08:01:35.357 に答える
0

これまで誰もやっていなかったので、タイマー アプローチを導入します。この 2 つ (BackgroundWorker と Timer) を組み合わせようとしましたが、意味がありませんでした。

複数のインスタンスがスレッドごとにデータを要求できるようにするメカニズムが必要でした。また、その間にある程度の間隔が必要でした。

試してみた後、タイマーアプローチのみでうまくいくことができると考えました。

public void ConnectDataProvider()
    {
        timer = new Timer(new TimerCallback(tCallback), null, 0, Timeout.Infinite);            
    }

private void tCallback(object state)
    {
        timer.Dispose();
        // time consuming task
        WriteData();
        timer = new Timer(new TimerCallback(tCallback), null, 5000, Timeout.Infinite);
    }

これは、John Saunders が同様の (しかし異なる) 問題について提案したものです。それは仕事をするようです。にはWriteData()同期 HttpWebRequest があるため、タイムアウトを処理できます。

私の質問は次のとおりです。タイマー オブジェクトの新しいインスタンス化のコストはどれくらいですか? つまり、それを達成するためのより良い方法はありますか?

注: WebRequest の非同期アプローチは機能しません。試してみました。それがサーバーのやり方であるかどうかは、今のところわかりません。

于 2009-08-18T11:44:45.157 に答える