C# 使用线程-添加到集合 列表数据=新列表(); foreach(id中的int-id){ var myThread=新线程(新线程开始(工作)); myThread.Start(id); } 工作(){ }
方法对接收到的id进行一些处理,然后将结果添加到数据列表中?如何从每个线程向集合添加数据?我的代码是什么样子的?谢谢,您可以从线程传递和检索数据(使用回调)。看 示例:C# 使用线程-添加到集合 列表数据=新列表(); foreach(id中的int-id){ var myThread=新线程(新线程开始(工作)); myThread.Start(id); } 工作(){ },c#,multithreading,C#,Multithreading,方法对接收到的id进行一些处理,然后将结果添加到数据列表中?如何从每个线程向集合添加数据?我的代码是什么样子的?谢谢,您可以从线程传递和检索数据(使用回调)。看 示例: List<int> data=new List<int>(); foreach(int id in ids){ var myThread=new Thread(new ThreadStart(Work)); myThread.Start(id); } Work(){ } 公共类Som
List<int> data=new List<int>();
foreach(int id in ids){
var myThread=new Thread(new ThreadStart(Work));
myThread.Start(id);
}
Work(){
}
公共类SomeClass
{
公共静态列表数据=新列表();
公共静态只读对象obj=新对象();
公共方法(int[]id)
{
foreach(id中的int-id)
{
工作w=新工作();
w、 数据=id;
w、 callback=ResultCallback;
var myThread=新线程(新线程开始(w.DoWork));
myThread.Start();
}
}
公共静态void ResultCallback(int d)
{
锁(obj)
{
数据.添加(d);
}
}
}
公共委托void ExampleCallback(int数据);
课堂作业
{
公共int数据{get;set;}
公共示例回调;
公共工作
{
WriteLine(“实例线程过程.Data={0}”,Data);
if(回调!=null)
回调(数据);
}
}
您可以从线程传递和检索数据(使用回调)。看
示例:
List<int> data=new List<int>();
foreach(int id in ids){
var myThread=new Thread(new ThreadStart(Work));
myThread.Start(id);
}
Work(){
}
公共类SomeClass
{
公共静态列表数据=新列表();
公共静态只读对象obj=新对象();
公共方法(int[]id)
{
foreach(id中的int-id)
{
工作w=新工作();
w、 数据=id;
w、 callback=ResultCallback;
var myThread=新线程(新线程开始(w.DoWork));
myThread.Start();
}
}
公共静态void ResultCallback(int d)
{
锁(obj)
{
数据.添加(d);
}
}
}
公共委托void ExampleCallback(int数据);
课堂作业
{
公共int数据{get;set;}
公共示例回调;
公共工作
{
WriteLine(“实例线程过程.Data={0}”,Data);
if(回调!=null)
回调(数据);
}
}
首先,您需要用锁保护多线程访问。其次,您需要将参数传递给线程(或者使用lambda,它可以捕获局部变量;注意,如果捕获循环变量,它将在循环期间更改值,因此您应该有一个局部副本)
objectcollectionlock=newobject();
列表数据=新列表();
foreach(id中的int-id)
{
螺纹t=新螺纹(工人);
t、 启动(id);
}
无效工作对象(对象o)
{
int id=(int)o;
锁(收集锁)
{
数据。添加(id);
}
}
首先,您需要用锁保护多线程访问。其次,您需要将参数传递给线程(或者使用lambda,它可以捕获局部变量;注意,如果捕获循环变量,它将在循环期间更改值,因此您应该有一个局部副本)
objectcollectionlock=newobject();
列表数据=新列表();
foreach(id中的int-id)
{
螺纹t=新螺纹(工人);
t、 启动(id);
}
无效工作对象(对象o)
{
int id=(int)o;
锁(收集锁)
{
数据。添加(id);
}
}
如果您使用的是.NET 4,我强烈建议您改用并行扩展。例如:
object collectionLock = new object();
List<int> data = new List<int>();
foreach (int id in ids)
{
Thread t = new Thread(Worker);
t.Start(id);
}
void Worker(object o)
{
int id = (int)o;
lock(collectionLock)
{
data.Add(id);
}
}
其中工作
为:
var list = ids.AsParallel()
.Select(Work)
.ToList();
这样它就可以适当地接收id
。如果您不喜欢方法转换,可以添加lambda表达式:
public int Work(int id)
{
...
}
无论哪种方式,这都可以避免创建超出实际需要的线程,并且可以处理线程安全方面的问题,而无需您自己管理锁。如果您使用的是.NET 4,我强烈建议您改用并行扩展。例如:
object collectionLock = new object();
List<int> data = new List<int>();
foreach (int id in ids)
{
Thread t = new Thread(Worker);
t.Start(id);
}
void Worker(object o)
{
int id = (int)o;
lock(collectionLock)
{
data.Add(id);
}
}
其中工作
为:
var list = ids.AsParallel()
.Select(Work)
.ToList();
这样它就可以适当地接收id
。如果您不喜欢方法转换,可以添加lambda表达式:
public int Work(int id)
{
...
}
无论采用哪种方式,都可以避免创建超出实际需要的线程,并在不必自己管理锁的情况下处理线程安全方面的问题。您需要手动管理锁定集合或使用.NET的一个并发集合。我建议将任务用于像这样简单的事情,不过,它巧妙地管理了线程造成的许多复杂性,并将引入一些非常有用的编程概念(如果你还不知道的话)。你肯定应该坚持他的方法。你需要手动锁定集合,或者使用.NET的一个并发集合。我建议将任务用于像这样简单的事情,不过,它巧妙地管理了线程造成的许多复杂性,并将引入一些非常有用的编程概念(如果你还不知道的话)。你绝对应该坚持他的方法。WRT:“你不能捕获循环变量”(它实际上可以被捕获——它总是同一个变量;-)来绕过这个问题。。。细节我使用
foreach(var x in…{var x=x;…}
,这很重要。@pst:是的,我的意思就是这个。捕获的变量在循环中被重用,因此捕获它并使用简单的方法会带来意外的行为。@pst:编辑答案以使其更清楚。谢谢你的建议