2

ここで提案されているように、マルチスレッドを実装しようとしています: Spawn Multiple Threads for work then wait until all finished

コードは次のようになります。

var resetEvent = new ManualResetEvent(false);
            var clientsCount = IDLocal.UserSessions.Count;

            // Load sessions:
            IDLocal.UserSessions = new IDSessions();

            // Start thread for each client 
            foreach (IDSession session in IDLocal.UserSessions)
            {
                var clnt = session;
                new Thread(
                    delegate()
                    {
                        Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
                        clnt.FailedToRespond = !this.SendDirect(data, this.GetHostAddress(clnt.HostName), clnt.PortNumber);

                        // If we're the last thread, signal 
                        if (Interlocked.Decrement(ref clientsCount) == 0) resetEvent.Set();
                    })
                    .Start();
            }

ここで ReSharper の警告が表示されます。if (Interlocked.Decrement(ref clientsCount) == 0)

変更されたクロージャ (clientsCount) にアクセスしていることを示唆しています

それは有効な提案ですか?

4

1 に答える 1

3

警告は、次のようなコードをカバーすることを目的としています

int i = 1;
Func<int> f = () => i + 1;
i = 2;
int j = f(); // What does this set j to?

iを呼び出すときに、 の更新された値が使用されますf。警告は、これを次のように変更することを提案しています

int i = 1;
int icopy = i;
Func<int> f = () => icopy + 1;
i = 2;
int j = f(); // Now what does this set j to?

デリゲートが作成されたときのf値を確認したい場合。iループのコンテキストではforeach、それ以外の場合、直感的でない動作を取得するのは非常に簡単です。foreachまさにこれが原因で、C# 5のループの意味が変更されました。

キャプチャされた変数への変更を確認したいので、コード内の何も変更しないでください。

于 2012-09-20T22:02:19.463 に答える