多个线程在C#中调用相同的方法
我有以下C#代码片段,我在其中模拟了我的问题。 在这个程序中,我有一个调用ReadRooms方法的Service函数。 现在我在不同的线程上调用服务方法。 我原以为ServiceCall和ReadRooms方法都会被平分,但是我得到的结果不正确。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication1 { class Program { public static void ReadRooms(int i) { Console.WriteLine("Reading Room::" + i); Thread.Sleep(2000); } public static void CallService(int i) { Console.WriteLine("ServiceCall::" + i); ReadRooms(i); } static void Main(string[] args) { Thread[] ts = new Thread[4]; for (int i = 0; i { int temp = i; CallService(temp); }); ts[i].Start(); } for (int i = 0; i < 4; i++) { ts[i].Join(); } Console.WriteLine("done"); Console.Read(); } } }
你仍然在“捕获循环变量”。 当i
已被捕获时,你正在创造一个temp
但为时已晚。
试试这个:
for (int i = 0; i < 4; i++) { int temp = i; // outside the lambda ts[i] = new Thread(() => { //int temp = i; // not here CallService(temp); }); ts[i].Start(); }
你应该把这一行
int temp = i;
在线程创建之前
for (int i = 0; i < 4; i++) { int temp = i; ts[i] = new Thread(() => CallService(temp)); ts[i].Start(); }
这样,您将创建将由lambda表达式使用的i的本地副本。
您的线程操作正在关闭变量i
而不是其当前值。 因此,线程读取i
和for循环中的增量之间存在竞争。 您可以将其作为参数传递:
ts[i] = new Thread(index => { CallService((int)index); }); ts[i].Start(i);
或者你可以将temp
的副本移动到循环内部而不是线程动作:
for (int i = 0; i < 4; i++) { int temp = i; ts[i] = new Thread(() => { CallService(temp); }); ts[i].Start(); }