2

WrapPanel のパフォーマンスを向上させるために、WP7 アプリにスレッドを導入しました。List1 つのリストに長いItem-objects があり、1 つずつ別の `List に追加されます。次の 2 つのリストがあります。

public List<Item> OriginalItems;
public List<Item> CopyOfItems;

イベント ハンドラー内に配置されるロジックBackgroundWorker.DoWorkは次のとおりです。

workerThread.DoWork += new DoWorkEventHandler((object sender, DoWorkEventArgs e) =>
{
    foreach (var item in OriginalItems)
    {
        Deployment.Current.Dispatcher.BeginInvoke(() =>
        {
            CopyOfItems.Add(item);
        });

        // I feel sooo sleepy
    }
});

これで、コメントを - に置き換えると問題なく動作しますが、これThread.Sleep(150)より少ない (場合によっては大きな値を使用する場合もある) と、コードが同じ要素に複数回続けて配置されます。

これはなぜですか、どうすれば修正できますか?

4

1 に答える 1

5

これは C# の既知の問題であり、実際には C# 5 で修正されていforeachます。ラムダ式のループからループ変数をキャプチャすると、 1 つの変数がキャプチャされます。その変数はループを通じてその値を変更します。そのため、「元の」反復が完了した後にラムダ式から作成されたデリゲートを実行すると、代わりに「現在の」反復からの値が表示されます。

簡単な回避策は、ループ内で反復変数のコピーを宣言して初期化し、それをキャプチャすることです。

foreach (var item in OriginalItems)
{
    var copy = item;
    Deployment.Current.Dispatcher.BeginInvoke(() =>
    {
        CopyOfItems.Add(copy);
    });

    // I feel sooo sleepy
}

詳細については、Eric Lippert のブログ記事「有害と見なされるループ変数を閉じる」を参照してください。

ところで、実際のコードは実際にループ内で何らかの作業を行っていますか? UIスレッドの作業をいくつかのチャンクに分割する以外に重要なことを行うためにスレッドを実際に使用していることは明らかではありませんBackgroundWorker.

于 2012-07-11T07:10:37.767 に答える