理解线程计数为什么不增加
本文关键字:为什么不 增加 线程 | 更新日期: 2023-09-27 18:17:24
我不明白为什么用这段代码
static void Main(string[] args)
{
Console.WriteLine("START PROGRAMN-----------------------------------");
test();
Console.WriteLine("END PROGRAMN-----------------------------------");
Console.Read();
}
[ThreadStatic]
private static int i;
private static void test()
{
for (i = 0; i < 2; i++)
{
var bw = new BackgroundWorker();
// define the event handlers
bw.DoWork += (sender, args) =>
{
Console.WriteLine("START Thread-------------");
Console.WriteLine("Print:" + i);
};
bw.RunWorkerCompleted += (sender, args) =>
{
Console.WriteLine("END Thread-------------");
if (args.Error != null)
{
Console.WriteLine(args.Error.ToString());
}
};
bw.RunWorkerAsync(); // starts the
}
}
它将在控制台中显示:
START PROGRAMN-----------------------------------
END PROGRAMN-----------------------------------
START Thread-------------
Print:0
END Thread-------------
START Thread-------------
Print:0
END Thread-------------
为什么第二次打印没有显示打印1?
我认为第一次迭代是正确的,因为我看到print: 0,但在第二次为什么我没有看到print: 1?
EDIT FOR answer
没有[ThreadStatic]static void Main(string[] args)
{
Console.WriteLine("START PROGRAMN-----------------------------------");
test();
Console.WriteLine("END PROGRAMN-----------------------------------");
Console.Read();
}
[ThreadStatic]
private static int i;
private static void test()
{
for (i = 0; i < 2; i++)
{
var bw = new BackgroundWorker();
// define the event handlers
bw.DoWork += (sender, args) =>
{
Console.WriteLine("START Thread-------------");
Console.WriteLine("Print:" + i);
};
bw.RunWorkerCompleted += (sender, args) =>
{
Console.WriteLine("END Thread-------------");
if (args.Error != null)
{
Console.WriteLine(args.Error.ToString());
}
};
bw.RunWorkerAsync(); // starts the
}
}
它将在控制台中显示:
START PROGRAMN-----------------------------------
END PROGRAMN-----------------------------------
START Thread-------------
Print:2
END Thread-------------
START Thread-------------
Print:2
END Thread-------------
为什么第一次打印不显示打印0,第二次打印1?
为什么显示2?
我认为您没有真正理解这里的ThreadStatic
属性。这意味着,根据定义,Indicates that the value of a static field is unique for every thread.
,这意味着值是唯一的主线程(你正在创建BackgroundWorkers)和BackgroundWorkers,这将始终具有默认值0的i
。
忘掉你没有正确使用的ThreadStatic
吧。这不是你需要的东西。你试图绕过的问题是因为否则你的结果得到最新的值,因为DoEvent没有在它已经改变的第一个线程上启动。你最终会得到一个竞态条件。您确实需要使用参数来清除变量的本地实例。最简单的方法是像这样修改代码
for (int i = 0; i < 2; i++)
{
var bw = new BackgroundWorker();
// define the event handlers
bw.DoWork += (sender, args) =>
{
// get the argument
var value = args.Argument.ToString();
Console.WriteLine("START Thread-------------");
Console.WriteLine("Print:" + value);
};
bw.RunWorkerCompleted += (sender, args) =>
{
Console.WriteLine("END Thread-------------");
if (args.Error != null)
{
Console.WriteLine(args.Error.ToString());
}
};
bw.RunWorkerAsync(i); // starts the thread with arguments
}
检查你的控制台。WriteLine("Print:" + i);'在lambda内部。在for循环内,"Print:"+ i不会被计算和连接。它将出现在您的匿名方法中,并且仅在该方法运行时才会被连接。
因为你的[ThreadStatic]属性,int i不能在线程间共享。每个正在执行的线程都有一个单独的字段实例,并独立地设置和获取该字段的值。如果在不同的线程上访问该字段,它将包含不同的值。"
int I将被实例化,您将获得int的默认值