【发布时间】:2018-09-29 07:42:24
【问题描述】:
在下面的代码中,为什么我们没有得到 NullReference 异常并且 var2 的值是 56 虽然 TestMethod 肯定在 'Messagebox' 行之前完成了?
我阅读了来自 Eric Lippert 的 this 的精彩回答和 this 的博文,但我仍然不明白。
void TestMethod()
{
int var1 = 10;
List<long> list1 = new List<long>();
for (int i = 0; i < 5; i++)
list1.Add(i);
ThreadPool.QueueUserWorkItem(delegate
{
int var2 = var1;
Thread.Sleep(1000);
list1.Clear();
MessageBox.Show(var2.ToString());
});
var1 = 56;
}
【问题讨论】:
-
您链接到我的答案是关于 C,而不是 C#。托管内存语言不存在在其生命周期结束后访问变量的问题,因为内存是托管,因此这永远不会发生。
-
您不一定会在新线程中得到 var2 为 56。你写了一个竞态条件;线程 race 来确定谁首先获得分配,并且您无法保证哪个线程将获胜。
-
你说你期望一个空解引用,但是你认为哪个引用是空的?您的程序中没有空引用!
-
@EricLippert,关于竞争条件,我明白了你的意思,但是如果我们重新排序前两行(
int var2 = var1和Thread.Sleep)并让调用者方法完成它的工作,我们仍然得到相同的结果。也许这里有一些我不知道的与实现相关的东西。 -
@EricLippert,关于空引用,我预计当
TestMethod方法完成时,它的堆栈被删除,所以list1变量。
标签: c# .net multithreading closures local-variables