访问修改后的闭包问题

时间:2011-01-12 23:32:14

标签: c# multithreading linq

进行了一些搜索,但找不到我在这里遇到的相同情况。

以下是我担心的片段:

    var threadsafeVacantStats = new Dictionary<Thread, StatsNode>();
    var threadSafeVacantLocker = new Object();
    var threadsafeZoneStats = new Dictionary<Thread, StatsNode>();
    var threadSafeZoneLocker = new Object();
    Parallel.ForEach(m_TeamAreasByZone[zone.ContainerID], team =>
    {
        var tempVacantStatNode = CreateASyncStatsNodes(threadSafeVacantLocker, threadsafeVacantStats);
        var tempZoneStatNode = CreateASyncStatsNodes(threadSafeZoneLocker, threadsafeZoneStats);
        //...other stuff
    }

这是它正在调用的函数:

private static StatsNode CreateASyncStatsNodes(object threadSafeLocker, Dictionary<Thread, StatsNode> threadsafeTeamStats)
{
    StatsNode tempStatsNode;
    var currentThread = Thread.CurrentThread;
    lock (threadSafeLocker)
    {
        if (!threadsafeTeamStats.ContainsKey(currentThread))
            threadsafeTeamStats[currentThread] = new StatsNode(0, 0);

        tempStatsNode = threadsafeTeamStats[currentThread];
    }
    return tempStatsNode;
}

对我来说,这看起来很好,但是resharper正在给第二次调用CreateASyncStatsNodes发出警告(第一次调用很好)。 根据它的建议,它将块变为:

var threadsafeVacantStats = new Dictionary<Thread, StatsNode>();
var threadSafeVacantLocker = new Object();
var threadsafeZoneStats = new Dictionary<Thread, StatsNode>();
var threadSafeZoneLocker = new Object();
object locker = threadSafeZoneLocker;
Dictionary<Thread, StatsNode> stats = threadsafeZoneStats;
Parallel.ForEach(m_TeamAreasByZone[zone.ContainerID], team =>
    {
        var tempVacantStatNode = CreateASyncStatsNodes(threadSafeVacantLocker, threadsafeVacantStats);
        var tempZoneStatNode = CreateASyncStatsNodes(locker, stats);
        //...
    }

这对我来说并没有多大意义,似乎并没有真正修复任何(如果它甚至在第一时间被破坏)。 resharper错误地标记了警告,还是我错过了什么?

2 个答案:

答案 0 :(得分:4)

Resharper不知道Parallel.ForEach立即执行传递的lambda。它假设这个lambda可以在以后执行,当关闭将被修改,这可能会产生一些问题。你可以忽略这个警告。

答案 1 :(得分:2)

ReSharper给你的确切警告是什么?请记住静态分析并不完美,我想说ReSharper很可能犯了一个错误。原始代码对我来说很好。