带锁的c#线程
本文关键字:线程 | 更新日期: 2023-09-27 18:17:26
我想我在这里遗漏了一些基础知识,无法找出问题所在。
下面程序的输出不符合预期。有谁能帮我理解一下这个问题吗?
using System;
using System.Threading;
public class Program
{
private static readonly object _lock = new object();
public static void Main()
{
for (var i = 0; i < 10; i++)
{
//Console.WriteLine("Start "+i);
System.Threading.Thread thread = new System.Threading.Thread(() => ExecuteInBackground(i));
thread.IsBackground = true;
thread.Start();
}
}
private static void ExecuteInBackground(Object obj)
{
lock (_lock)
{
Console.WriteLine("A "+obj);
test.ttt(obj);
}
}
}
public static class test
{
public static void ttt(object obj)
{
Console.WriteLine("B "+ obj);
}
}
我期望在输出中看到0到9 ..但实际输出如下…
A 1
B 1
A 1
B 1
A 3
B 3
A 4
B 4
A 5
B 5
A 6
B 6
A 7
B 7
A 8
B 8
A 9
B 9
A 10
B 10
感谢您的帮助。
请随意使用https://dotnetfiddle.net/nYfbMU
中的代码谢谢,Reddy .
修改如下:
for (var i = 0; i < 10; i++)
{
//Console.WriteLine("Start "+i);
System.Threading.Thread thread = new System.Threading.Thread(() => ExecuteInBackground(i));
:
for (var i = 0; i < 10; i++)
{
var temp = i;
//Console.WriteLine("Start "+i);
System.Threading.Thread thread = new System.Threading.Thread(() => ExecuteInBackground(temp));
这是闭包问题。参见为什么在lambda表达式中使用迭代变量是不好的
原始代码不工作的原因如你所期望的,以及为什么临时变量,是因为() => ExecuteInBackground(i)
就像说"在未来的某个时候,我希望这个新线程调用ExecuteInBackground
方法,在调用时传递任何值I "。由于循环变量在循环开始时进入作用域,在循环结束后退出作用域,因此i的值在调用Thread和执行ExecuteInBackground之间发生变化。通过在循环中使用一个临时变量,它在循环的每次迭代中都超出了作用域,每个线程对ExecuteInBackground的调用实际上是在每次调用中获得一个具有不变值的不同变量,并且i的下一次递增不会把事情搞砸。
这对我很有用。
using System;
using System.Threading;
public class Program
{
private static readonly object _lock = new object();
public static void Main()
{
for (var i = 0; i <= 10; i++)
{
fn(i);
}
Console.ReadLine();
}
private static void fn(int i)
{
System.Threading.Thread thread = new System.Threading.Thread(() => ExecuteInBackground(i));
thread.IsBackground = true;
thread.Start();
}
private static void ExecuteInBackground(Object obj)
{
lock (_lock)
{
Thread.Sleep(500);
Console.WriteLine("A "+obj);
test.ttt(obj);
}
}
}
public static class test
{
//private static readonly object _lock = new object();
public static void ttt(object obj)
{
//lock(_lock)
Console.WriteLine("B "+ obj);
}
}