0

私のアプリは、ユーザーがファイルをアップロードできるディレクトリを監視します。新しいファイルが検出されると、キューに追加されます。キューを通過し、ファイルのアップロードが完了したかどうかを判断するタイマーがあります。完了したファイルがある場合は、最新のものを取得し、バックグラウンド タスクの実行を開始します (BackgroundWorker を使用)。

私の問題は、バックグラウンド タスクの実行中にタイマーを処理する方法がわからないことです。たとえば、タイマーが 10 秒に設定されていて、バックグラウンド ワーカーがまだ動作している場合、次の反復までタイマーが別のバックグラウンド ワーカーの実行をスキップするようにします。

また、各タスクの情報は Queue (ListView コントロール) に格納され、ListViewItem をバックグラウンド ワーカーに渡します。ListViewItem を渡すと副作用があるかどうか興味があります。

ありがとう!

4

6 に答える 6

1

すぐに処理できるファイルを別のキュー ( Queue< string> など) に保存し、BgWorker にそのキューを継続的にポーリングさせることができます。パフォーマンスも向上し、アイドル時間が短縮される可能性があります。Queue を (Monitor で) 保護し、Queue が空のときに BgWorker に Monitor.Wait を使用させる必要があります。

アイデアを得るには、この質問に対する Marc Gravell の回答を探してください。

于 2009-06-22T22:31:47.913 に答える
0

タスクを配置するスレッド キューを作成できます。バックグラウンド ワーカーがループしてキューからアイテムを取得し、作業を実行します。いくつかのことを考慮する必要があります。

  • キューはスレッド セーフである必要があり、キューが空の場合はバックグラウンド ワーカーをブロックし、アイテムが利用可能になったときにウェイクアップする必要があります。誰かがすでにこんなに素敵なキューを作っていると確信しています.
  • キューに投稿したアイテムは、別のスレッド (バックグラウンド ワーカー) で操作されます。これがスレッド セーフな方法で行われていることを確認してください (たとえば、メイン アプリケーションとバックグラウンド ワーカーの両方が変更するアイテムをキューにポストしないでください)。

別のより簡単なアプローチは、

  • アプリケーションでアイテムをキューに入れます。バックグラウンドワーカーを最初に 1 回キックオフします。
  • バックグラウンド ワーカーが完了したというイベントを取得したら、キューから次のアイテムを選択し、このアイテムでバックグラウンド ワーカーを再度開始します。
  • スレッドの安全性については引き続き考慮する必要があります。アイテムをバックグラウンド ワーカーに送信したら、バックグラウンド ワーカーだけが操作するようにします (たとえば、文字列を送信するだけの場合は、代わりにその文字列のコピーを送信します)。

タイマーについていけませんでした。バックグラウンドワーカーが終了した場合、イベントを取得する必要があり、終了したことがわかります。これをチェックするタイマーは必要ありません。

于 2009-06-22T22:46:59.490 に答える
0

あなたが話しているコードを見ずにこれに答えるのは本当に難しいです。ただし、複数の非同期イベント (ファイルのダウンロードの検出、キューへのファイルの追加、キューの処理) を同期する必要がある場合は、すべてのタスクを実行する単一の BackgroundWorker を作成することをお勧めします。次に、ワーカーで各ステップの状態を簡単にテストできます。複数のスレッドを作成してそれらを同期しようとすることは避けたいと思いますが、これは非常に問題があります。

また、バックグラウンド タスク情報を UI データ構造 (ListView コントロールなど) に格納することもありません。何かを表示する必要があるときに UI に警告するコールバックまたはイベントを BackgroundWorker に作成します。

于 2009-06-22T22:34:03.557 に答える
0

BackgroundWorker.IsBusy プロパティはあなたが探しているものですか?

于 2009-06-22T22:34:35.897 に答える
0

最も簡単にできることは、BackgroundWorker 内ですべての作業 (フォルダーのチェックを含む) を行うことです:しばらくスレッド。

とにかくフォルダーは非同期で更新されるため、ここでスレッドセーフなキューは必要ないと思います。したがって、必要なスレッドは 1 つだけですが、それを停止する方法が必要ですこれが、AutoResetEvent.WaitOne(time) が Sleep(time) よりも優れている理由です。メイン スレッドからイベントを通知して、バックグラウンド ワーカーを早期に終了させることができます。

于 2009-06-22T22:36:00.713 に答える
0

Timer.Tick ハンドラーで、BackgroundWorker.IsBusyプロパティをチェックして、別の作業の準備ができているかどうかを判断します。そうでない場合は、作業をスキップして、次の Tick まで待ちます。

于 2009-06-22T22:36:09.917 に答える