0

私は BackgroundWorkers をかなり使用してきましたが、この問題を経験したことはありません。私のプログラムは、何千ものパケットを生成するロジック アナライザーからの出力を分析します。フォーム内の ListView の更新が大幅に遅れるのを防ぐため (以前は見つかったものをそれぞれ報告していましたが、フォームは完全に応答しませんでした)、BackgroundWorker 内のパケットを一般的なリスト (List<Packet>) に収集しています。次に、n 個 (現在は 250 個) が見つかったとき、例外が発生したとき、または例外が完了したときに報告します。

List<Packet> を繰り返し処理しているときにコールバックで問題が発生し、「コレクションが変更されました」というエラーとともに InvalidOperationException が発生します。foreach 内のコレクションには触れていません (別のコレクションに追加していますが、繰り返し処理しているコレクションを変更する理由がわかりません。さらに、コメントアウトしても問題は解決しません)。 e.UserState をロックし、e.UserState をローカル スコープ List<Packet> に格納してロックしようとしても、何も機能しないようです。

コールバック メソッドのコードは次のとおりです。

void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar.Value = e.ProgressPercentage;
    packetsListView.SuspendLayout();
    lock ((List<Packet>)e.UserState)
    {
        foreach (Packet packet in (List<Packet>)e.UserState)
        {
            packets.Add(packet);
            ListViewItem item = new ListViewItem(string.Format("{0}ns", Math.Round(packet.StartSampleNumber * 41.666667)));
            item.Tag = packet;
            item.SubItems.Add(new ListViewItem.ListViewSubItem(item, packet.Description));
            packetsListView.Items.Add(item);
        }
    }
    packetsListView.ResumeLayout();

    statusLabel.Text = string.Format("Analyzing...found {0} {1}", packetsListView.Items.Count, packetsListView.Items.Count == 1 ? "packet" : "packets");
}
4

4 に答える 4

5

問題の簡単な説明は、DoWork イベント ハンドラーではなく、ProgressChanged イベント ハンドラーでロックを使用することです。これにより、UI スレッドがコレクションを反復している間で、ワーカー スレッドはコレクションを変更できます。

解決するのは簡単です。ワーカーで ReportProgress を呼び出した直後に新しいList<>を作成するだけです。UI スレッドは、リストへの参照を持つ唯一のスレッドになりました。ロックを使用する必要はなくなりました。

于 2010-10-02T12:11:07.483 に答える
0

foreach で反復しているコレクションを変更することはできません。packets.Addループ内でメソッドを呼び出していますが、この変数は、繰り返し処理しているのと同じコレクションを指しているforeachと思われます。packets

そうでない場合は、フォーム内で宣言するプライベートな静的フィールドをロックしてみてください。

private static object _syncRoot = new object();

その後:

lock (_syncRoot)
{
    ...
}
于 2010-10-02T12:02:51.790 に答える
0

このメソッドで作成packetすると、反復されたものをエイリアスすることはできません。

于 2010-10-02T12:25:01.760 に答える
0

パフォーマンスが大きな問題ではない場合、いくつかの並行セーフ コレクションを使用すると、かなりうまく機能することがわかりました。詳細はこちら

于 2010-10-02T12:11:42.893 に答える