我在C#.NET的程序中启动了最多5个线程。但有时这些线程中的某些线程甚至在分配给它的函数执行完成之前就会莫名其妙地退出或死亡。
它是随机发生的。如果我尝试通过放置断点来调试代码 - 它工作正常。
有时所有线程都完美地执行指定的函数。它们之间不共享任何资源。
Thread[] td = new Thread[5];
for (count = 4; count >= 0; --count)
{
ds[count] = dba.getData(ru[count]);
td[count] = new Thread(delegate() { runRule[count].performTask(ru[count], ds[count], count); });
td[count].Name = "Thread " + count.ToString();
td[count].Start();
Thread.Sleep(50);
}
如果我删除最后一行“Thread.Sleep(50)”,只有第一个线程开始运行,其余部分才会死亡。
有人可以解释为什么线程会死掉吗?
答案 0 :(得分:4)
我怀疑他们没有死 - 我怀疑问题是你实际上没有按照你认为的规则运行。在匿名方法中使用方法的局部变量时,将捕获变量本身。在这种情况下,您将捕获count
局部变量 - 然后更改它(随着循环计数器减少)。当count = 4开始运行时创建的线程开始运行时,count
可能为3 - 因此它将调用runRule[3].performTask(ru[3], ds[3], 3)
。实际上,count
可以在评估表达式时更改 ,这可能会带来很多乐趣。
绕过这个的方法是为循环的每次迭代设置一个不同的“局部”变量。这很容易做到:
Thread[] td = new Thread[5];
for (count = 4; count >= 0; --count)
{
int copy = count;
ds[count] = dba.getData(ru[count]);
td[count] = new Thread(delegate() {
runRule[copy].performTask(ru[copy], ds[copy], copy);
});
td[count].Name = "Thread " + count.ToString();
td[count].Start();
Thread.Sleep(50);
}
现在代表中捕获的唯一变量是copy
和runRule
/ ru
/ ds
- 我假设后三者不会改变。每次循环时都会创建copy
变量的新“实例”,因此更改不会相互干扰。
看看这是否有帮助 - 它至少是导致大规模混淆的潜在原因,可能就是问题所在。
答案 1 :(得分:1)
如果某个线程到达其执行路径的末尾,它将自动结束。在你的例子中,一旦线程完成了performTask方法,它就会退出。
如果你想要一个线程永远挂起(仅为了调试目的,因为你不希望在实际应用程序中闲置未使用的线程),你可以在线程运行的方法的末尾添加类似下面的内容
ManualResetEvent stayAlive = new ManualResetEvent(false);
stayAlive.WaitOne();