for循环里面添加多线程 for(int i = 0;i < 4;i ++){ 方法;}可不可以设计一个多线程 i=0一个线程拿任务 i=1 一个线程拿任务 这样的 有次序的拿任务了不怎么会多线程 讨教各大大哥了 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 通过循环启动多个线程是可以实现的,方法也不复杂。你可以自己去读一下MSDN里的相关部分。不过要通过多线程来加速运行是有条件的。一个是你要有能够在一个线程运行中(不是挂起时)还可以运行别的线程的机器,也就是说要有具备多线程能力的CPU。另一个则是你的线程运行时多数时间在等待外部资源,使得对CPU的利用率十分低下。如果这两个条件都不满足,那多线程不但不能加速,反而会显得更慢。 这样的话不建议使用Thread来建立专用线程,应该考虑使用线程池的ThreadPool.QueueWorkItem方法,或者使用Task类。如果是循环执行一个方法的话,没有数据共享的话且不要求顺序执行的话,可以用Parallel.For方法并行执行 可是多线程应该怎么设计了是for(int i =0;i <3;i++){Thread thread = new Thread(new ThreadStart(循环的方法))}就这样吗 可是这样会不会重复的?莫非循环的方法里面用LOCK关键字?这样的话感觉也不行啊 在里面加条件,比如for(int i =0;i <3;i++){if(i==0)Thread thread1 = new Thread(new ThreadStart(循环的方法))else if(i==1)Thread thread2 = new Thread(new ThreadStart(循环的方法))}除非你要处理相同的数据,否则不用锁定。线程执行完毕后会自动释放内存。这样比较麻烦,个人觉得循环里面写个带参数的委托比较好一点,把i做为参数使用。 for(int i =0;i <3;i++){任务=取任务();Thread thread = new Thread(new ThreadStart(() =>{执行(任务);}));} 从性能开销问题上来说 开启一个线程是很耗性能的,而楼主的意思大概是想用多线程来提高程序的性能,上面的答案对于少量的多线程还可以,如果for循环次数很多,就要用线程池了。 for 循环的多线程处理就用 Parallel.For public static int k = 0; for (int i = 0; i < 5; i++) { Thread thread = new Thread(new ThreadStart(new Program().GetTask)); thread.Name = i.ToString(); thread.Start(); } public void GetTask() { string task = ""; while (true) { k++; if (k > tasks.Count) { break; } lock (this) { task = tasks.ToArray().Skip(k - 1).First().ToString(); } SendMail2(task); } }我这样写了 还是会拿到重复数据从理论上来说应该不会了 可是他还是会拿到重复?为什么 最基本地,每一个线程内的程序执行时所使用的变量是私有变量,而不是共享的。例如for(int i = 0;i < 4;i ++){ var j=i; 方法_使用j而不是i;} 假设线程中共享对象引用,要比共享值类型的变量复杂一些。因为不同的变量也会可能指向相同的对象,所以使用var j=i;也可能指向共享的对象。这时候其实就需要类似var j=i.Clone();这种东西。但是概念显然是一样的。你就注意你的线程共享了变量就可能出乱子就对了。因为共享、你的上一条语句跟下一条语句之间同一个变量就完全可能被别人修改值的。比较笨的办法是加锁。但是没有办法做出更好的设计时,也会采取加锁的办法。或者当测试出来性能影响不大时,也会采取加锁的办法。 这其实是我所出的一个题目http://topic.csdn.net/u/20120302/09/f64f94d5-b032-43ba-baef-6f475355c262.html中要解决的问题,在这里可以给你说说思路。目的是多个线程协同的进行一项工作,这是异步工作的思路,我们看到有两个步骤:1.拿任务步骤2. 处理任务步骤。处理任务步骤必须是拿到任务才能处理的偶。我们就此改造一下; 注册任务处理: public event EventHandler HasTask; HasTask += new EventHander(Class_HasTaskCallBack); 拿任务的线程(threadGetTask): for(int i = 0;i < 4;i ++) { task = 拿方法(); HasTask.BeginInvoke(task, new EventArg(),null,null); //发出有新任务消息,非阻塞 } 处理任务的线程void Class_HasTask(object sender, EventArgs e){ MyTask task = sender as MyTask DoSomething....} 任务在一个线程里取,取到后再用线程执行,这样应该是不会出现取到相同任务问题的。至于你这个会取到同一个任务是很正常的,因为你只lock了取的时候,我简单的打个比方:比如你第一次取得任务,k=1,到了lock(this)进行取任务,这时候第二个线程启动,执行了k++,这时候k=2,请求lock(this)的时候进行等待,回到第一个线程,这时候进行取任务,其实是取了k=2的任务,然后解锁,第二个线程进行lock(this),也取任务,一样都取了k=2的任务。 一个不得已的加锁例子,例如private List<string> tasks= new List<string>{"任务1","任务2","任务2"};for(int i = 0;i < 4;i ++){ 注册线程(调用方法);}void 调用方法(){ lock(tasks) { var tsk= tasks[0]; tasks.RemoveAt(0); ......使用tsk进行操作 }};这种,貌似必须共享tasks操作,线程不安全,所以需要加锁。但是既然这个这么简单,你完全可以在for循环中就把task[0]给复制下来(作为参数传递给线程执行方法),然后执行RemoveAt。也就是说子线程方法里边前两条代码都是放到主线程中执行,而子线程只是使用私有参数(绝不与其它子线程冲突了)来作为tsk进行操作。于是再主线程额外多执行了两条语句,花了微不足道的一点时间和空间,结果是子线程可以很好地并行操作了。无需加锁和阻塞。何乐而不为? 如果需要处理步骤的处理次序与获取任务for循环的处理次序完全一致,这里的问题就复杂一些,貌似需要引入队列的概念,处理子线程并不直接处理,而是将处理数据按照次序压入队列,而单独会有一个处理线程从队列中逐个提取任务并处理。 for (int i = 0; i < 10; i++) { int index = i; Thread thread = new Thread(new ThreadStart(delegate() { Console.WriteLine(index.ToString()); //要执行的代码 })); thread.Start(); } 我做了个例程,大家可以讨论一下http://blog.csdn.net/etudiant6666/article/details/7336521 序列化的问题 有一个List<int>,要全部加1,求最简单的写法。 100分给推荐几本学DELPHI入门的书 filestream写文件的时候为什么先转换为byte块 C#文件流操作,中文乱码问题求解! 高手救我啊.............. 世界杯结束,大病初愈,散分~~~~~~~~~~~~ WPF,请教一个递归查找元素的问题 帮帮忙?急急急急急 添加的文本文件的路径??? c++调用c#做的com问题 C# 上传文件时如何实现将doc、txt文件自动转换为pdf并保存?
{Thread thread = new Thread(new ThreadStart(循环的方法))
}
就这样吗 可是这样会不会重复的?莫非循环的方法里面用LOCK关键字?这样的话感觉也不行啊
在里面加条件,比如
for(int i =0;i <3;i++)
{
if(i==0)
Thread thread1 = new Thread(new ThreadStart(循环的方法))
else if(i==1)
Thread thread2 = new Thread(new ThreadStart(循环的方法))
}
除非你要处理相同的数据,否则不用锁定。线程执行完毕后会自动释放内存。
这样比较麻烦,个人觉得循环里面写个带参数的委托比较好一点,把i做为参数使用。
{
任务=取任务();
Thread thread = new Thread(new ThreadStart(() =>
{
执行(任务);
}
));
}
{
Thread thread = new Thread(new ThreadStart(new Program().GetTask));
thread.Name = i.ToString();
thread.Start(); } public void GetTask()
{
string task = ""; while (true)
{ k++;
if (k > tasks.Count)
{
break;
}
lock (this)
{
task = tasks.ToArray().Skip(k - 1).First().ToString();
}
SendMail2(task);
}
}
我这样写了 还是会拿到重复数据从理论上来说应该不会了 可是他还是会拿到重复?为什么
最基本地,每一个线程内的程序执行时所使用的变量是私有变量,而不是共享的。例如for(int i = 0;i < 4;i ++)
{
var j=i;
方法_使用j而不是i;
}
这其实是我所出的一个题目http://topic.csdn.net/u/20120302/09/f64f94d5-b032-43ba-baef-6f475355c262.html中要解决的问题,在这里可以给你说说思路。
目的是多个线程协同的进行一项工作,这是异步工作的思路,我们看到有两个步骤:
1.拿任务步骤
2. 处理任务步骤。处理任务步骤必须是拿到任务才能处理的偶。
我们就此改造一下; 注册任务处理:
public event EventHandler HasTask;
HasTask += new EventHander(Class_HasTaskCallBack); 拿任务的线程(threadGetTask):
for(int i = 0;i < 4;i ++)
{
task = 拿方法();
HasTask.BeginInvoke(task, new EventArg(),null,null); //发出有新任务消息,非阻塞
} 处理任务的线程
void Class_HasTask(object sender, EventArgs e)
{
MyTask task = sender as MyTask
DoSomething....}
任务在一个线程里取,取到后再用线程执行,这样应该是不会出现取到相同任务问题的。至于你这个会取到同一个任务是很正常的,因为你只lock了取的时候,我简单的打个比方:
比如你第一次取得任务,k=1,到了lock(this)进行取任务,这时候第二个线程启动,执行了k++,这时候k=2,请求lock(this)的时候进行等待,回到第一个线程,这时候进行取任务,其实是取了k=2的任务,然后解锁,第二个线程进行lock(this),也取任务,一样都取了k=2的任务。
一个不得已的加锁例子,例如private List<string> tasks= new List<string>{"任务1","任务2","任务2"};for(int i = 0;i < 4;i ++)
{
注册线程(调用方法);
}void 调用方法()
{
lock(tasks)
{
var tsk= tasks[0];
tasks.RemoveAt(0);
......使用tsk进行操作
}
};这种,貌似必须共享tasks操作,线程不安全,所以需要加锁。但是既然这个这么简单,你完全可以在for循环中就把task[0]给复制下来(作为参数传递给线程执行方法),然后执行RemoveAt。也就是说子线程方法里边前两条代码都是放到主线程中执行,而子线程只是使用私有参数(绝不与其它子线程冲突了)来作为tsk进行操作。于是再主线程额外多执行了两条语句,花了微不足道的一点时间和空间,结果是子线程可以很好地并行操作了。无需加锁和阻塞。何乐而不为?
{
int index = i;
Thread thread = new Thread(new ThreadStart(delegate()
{
Console.WriteLine(index.ToString()); //要执行的代码
}));
thread.Start();
}
http://blog.csdn.net/etudiant6666/article/details/7336521