C#多线程处理的另一个问题,刚刚忘了问,新开一帖继续问
刚刚那贴是这个http://bbs.csdn.net/topics/390663254?page=1#post-396281062
使用
for (int i = 0; i < listBox1.Items.Count; i++)
{
Thread Th1 = new Thread(showForm2);
Th1.Start(listBox1.Items[i]);
}
是可以创建线程,但没办法控制数量,这个是一下子就全部开了
我的新问题是,用户将几十个文件拖入listbox,经过对电脑性能的测试,我希望最多同时开4个线程进行处理。
现在的问题是,如何判断有线程已经处理完了?
比如,用户拖了100张照片到listbox,点击开始处理后,程序会开4个进行处理,因为处理的速度不一样,有的进程快一些,就处理好了,处理好的进程退出后,再开一个新的线程处理下一张,直到处理完毕,当文件已经全部处理完或已经有线程在处理的时候,就不再开线程了,总之最大同时保持有4个线程就好了!要怎么做? --------------------编程问答-------------------- http://msdn.microsoft.com/zh-cn/library/system.threading.threadpool.setmaxthreads(v=vs.100).aspx --------------------编程问答-------------------- 如果你的 showForm2 方法原本就是一个顺序执行的方法,那么可以写
var tsks = new List<Task>();--------------------编程问答-------------------- 那么你可以使用ThreadPool类。 --------------------编程问答-------------------- 使用线程对象的Aborted属性判断线程是否结束 --------------------编程问答-------------------- 如果你不想一下子开count个,那么你就别写 i<listBox1.Items.Count 呗。 --------------------编程问答--------------------
for (int i = 0; i < listBox1.Items.Count; i++)
{
tsks.Add(new Task(()=>showForm2(listBox1.Items[i])));
}
Task.WaitAll(tsks.ToArray());
是的,是一个图片处理的程序,中间有for,while等循环,但一定会执行完的 --------------------编程问答-------------------- 好像没有解决问题的答案。。。顶上去 --------------------编程问答-------------------- 一开始第一个想到的办法就是这个,完了才想到要控制线程的数量,毕竟CPU处理能力有限。
var tsks = new List<Task>();
for (int i = 0; i < listBox1.Items.Count; i++)
{
tsks.Add(new Task(()=>showForm2(listBox1.Items[i])));
}
Task.WaitAll(tsks.ToArray());
这个代码我试了试,没看出来怎么用的。能再给个解决方案吗?麻烦你了! --------------------编程问答--------------------
--------------------编程问答-------------------- ThreadPool我之前还真没用过,现学现卖,上面的代码我测过了,没问题,应该可以符合你的需求
ThreadPool.SetMaxThreads(4, 4);
for (int i = 0; i < listBox1.Items.Count; i++)
{
System.Threading.WaitCallback waitCallback = new WaitCallback(showForm2);
ThreadPool.QueueUserWorkItem(waitCallback, listBox1.Items[i]);
}
public void showForm2(object o)
{
MessageBox.Show(o.ToString());
}
ThreadPool.SetMaxThreads(4, 4);
但是这两个参数我还没完全理解 --------------------编程问答--------------------
感谢,经过测试,完全达到要求
没错,目前我的水平暂时就是这样了,遇到问题就实时求助,然后拼接进自己的代码。。。。希望有天自己也能成为高手。。。 --------------------编程问答--------------------
我也无法理解,我试着修改参数4,4 发现比如修改为3,1的时候,还是会执行所有的线程。。。 --------------------编程问答-------------------- 又试了下,还是不够理想啊,貌似只有设置为4以上的数时才有效,低于4就不受控制了。。。怎么回事呢 --------------------编程问答--------------------
ThreadPool我之前还真没用过,现学现卖,上面的代码我测过了,没问题,应该可以符合你的需求
ThreadPool.SetMaxThreads(4, 4);
但是这两个参数我还没完全理解
感谢,经过测试,完全达到要求
没错,目前我的水平暂时就是这样了,遇到问题就实时求助,然后拼接进自己的代码。。。。希望有天自己也能成为高手。。。
我现在有时间就到csdn看看,看到别人的问题,会的我就说说,不会而且有价值我就收藏了,坐等大神的答案,能学到不少东西。慢慢学吧~共勉啊~ --------------------编程问答--------------------
ThreadPool我之前还真没用过,现学现卖,上面的代码我测过了,没问题,应该可以符合你的需求
ThreadPool.SetMaxThreads(4, 4);
但是这两个参数我还没完全理解
感谢,经过测试,完全达到要求
没错,目前我的水平暂时就是这样了,遇到问题就实时求助,然后拼接进自己的代码。。。。希望有天自己也能成为高手。。。
我现在有时间就到csdn看看,看到别人的问题,会的我就说说,不会而且有价值我就收藏了,坐等大神的答案,能学到不少东西。慢慢学吧~共勉啊~
关于我的问题我想到了一个间接的办法,那就是预估线程需要执行的时间,等到了一定的时间再开新线程,比如,我测试一个线程处理数据需要10分钟,我就等12分钟再开新线程,不过这样虽然可以,就是太不科学了,CPU利用率也不高,顶多是替代了手工操作而已了。坐等高手的答案吧。。。 --------------------编程问答-------------------- 那没必要了,ThreadPool就是把所有的线程加入等待队列,比如目前最大4个进程,有一个结束的时候,马上就会启动下一个; --------------------编程问答--------------------
又试了下,还是不够理想啊,貌似只有设置为4以上的数时才有效,低于4就不受控制了。。。怎么回事呢
ThreadPool我之前还真没用过,现学现卖,上面的代码我测过了,没问题,应该可以符合你的需求
ThreadPool.SetMaxThreads(4, 4);
但是这两个参数我还没完全理解
感谢,经过测试,完全达到要求
没错,目前我的水平暂时就是这样了,遇到问题就实时求助,然后拼接进自己的代码。。。。希望有天自己也能成为高手。。。
你是四核电脑吧
不能将辅助线程的数目或 I/O 完成线程的数目设置为小于计算机的处理器数目 --------------------编程问答--------------------
又试了下,还是不够理想啊,貌似只有设置为4以上的数时才有效,低于4就不受控制了。。。怎么回事呢
ThreadPool我之前还真没用过,现学现卖,上面的代码我测过了,没问题,应该可以符合你的需求
ThreadPool.SetMaxThreads(4, 4);
但是这两个参数我还没完全理解
感谢,经过测试,完全达到要求
没错,目前我的水平暂时就是这样了,遇到问题就实时求助,然后拼接进自己的代码。。。。希望有天自己也能成为高手。。。
你是四核电脑吧
不能将辅助线程的数目或 I/O 完成线程的数目设置为小于计算机的处理器数目
是I5 2430笔记本CPU,双核4线程,是这个原因吗? --------------------编程问答-------------------- http://msdn.microsoft.com/zh-cn/library/system.threading.threadpool.setmaxthreads(v=vs.110).aspx
应该是,msdn备注里说明了这一点 --------------------编程问答-------------------- 继续顶上去啊 --------------------编程问答-------------------- 顶上去啊啊啊 --------------------编程问答-------------------- 看来果然是周末没人回帖呀 --------------------编程问答-------------------- 使用多线程+线程安全队列,将所有的任务抽象为一个过程+为过程提供的对象,即委托+参数
记事本写的代码,排版乱了见谅
using System;
using System.Threading;
using System.Collections;
class a{
static void Main(){
qthread qth=new qthread(new ParameterizedThreadStart(run));//新建qthread实例,传入方法
for(int i=0;i<10;i++)//将要进行操作的数据放入队列
{
qth.works.Enqueue(i.ToString());
}
qth.DoWork(4);//4线程
}
static void run(object obj)//工作方法
{
string s;
Queue works=obj as Queue;
while(works.Count>0)
{
s=works.Dequeue() as string;
int i=random.Next(1000,4001);
Console.WriteLine("thread:{0},id:{1},obj:{2},sleep:{3}",Thread.CurrentThread.Name,Thread.CurrentThread.ManagedThreadId,s,i.ToString());
Thread.Sleep(i);//随机sleep1-4秒,代替耗时
Console.WriteLine("thread:{0},id:{1},obj:{2}..........ok!",Thread.CurrentThread.Name,Thread.CurrentThread.ManagedThreadId,s);
}
}
volatile static Random random=new Random();
}
class qthread{
ParameterizedThreadStart pts=null;
public volatile Queue works=Queue.Synchronized(new Queue());//线程安全队列,存放参数
public qthread(ParameterizedThreadStart pts)
{
this.pts=pts;
}
public void DoWork(int count)
{
for(int i=0;i<count;i++)
{
Thread t = new Thread(pts);
t.Name=("qthread#"+i.ToString());
t.IsBackground = false;
t.Start(works);
}
}
}
编译执行:csc qthread.cs && qthread
结果:
thread:qthread#0,id:3,obj:0,sleep:1207--------------------编程问答--------------------
thread:qthread#2,id:5,obj:3,sleep:2454
thread:qthread#1,id:4,obj:1,sleep:1239
thread:qthread#3,id:6,obj:2,sleep:1183
thread:qthread#3,id:6,obj:2..........ok!
thread:qthread#3,id:6,obj:4,sleep:2779
thread:qthread#0,id:3,obj:0..........ok!
thread:qthread#0,id:3,obj:5,sleep:2182
thread:qthread#1,id:4,obj:1..........ok!
thread:qthread#1,id:4,obj:6,sleep:3887
thread:qthread#2,id:5,obj:3..........ok!
thread:qthread#2,id:5,obj:7,sleep:2473
thread:qthread#0,id:3,obj:5..........ok!
thread:qthread#0,id:3,obj:8,sleep:1297
thread:qthread#3,id:6,obj:4..........ok!
thread:qthread#3,id:6,obj:9,sleep:3133
thread:qthread#0,id:3,obj:8..........ok!
thread:qthread#2,id:5,obj:7..........ok!
thread:qthread#1,id:4,obj:6..........ok!
thread:qthread#3,id:6,obj:9..........ok!
使用多线程+线程安全队列,将所有的任务抽象为一个过程+为过程提供的对象,即委托+参数
记事本写的代码,排版乱了见谅
using System;
using System.Threading;
using System.Collections;
class a{
static void Main(){
qthread qth=new qthread(new ParameterizedThreadStart(run));//新建qthread实例,传入方法
for(int i=0;i<10;i++)//将要进行操作的数据放入队列
{
qth.works.Enqueue(i.ToString());
}
qth.DoWork(4);//4线程
}
static void run(object obj)//工作方法
{
string s;
Queue works=obj as Queue;
while(works.Count>0)
{
s=works.Dequeue() as string;
int i=random.Next(1000,4001);
Console.WriteLine("thread:{0},id:{1},obj:{2},sleep:{3}",Thread.CurrentThread.Name,Thread.CurrentThread.ManagedThreadId,s,i.ToString());
Thread.Sleep(i);//随机sleep1-4秒,代替耗时
Console.WriteLine("thread:{0},id:{1},obj:{2}..........ok!",Thread.CurrentThread.Name,Thread.CurrentThread.ManagedThreadId,s);
}
}
volatile static Random random=new Random();
}
class qthread{
ParameterizedThreadStart pts=null;
public volatile Queue works=Queue.Synchronized(new Queue());//线程安全队列,存放参数
public qthread(ParameterizedThreadStart pts)
{
this.pts=pts;
}
public void DoWork(int count)
{
for(int i=0;i<count;i++)
{
Thread t = new Thread(pts);
t.Name=("qthread#"+i.ToString());
t.IsBackground = false;
t.Start(works);
}
}
}
编译执行:csc qthread.cs && qthread
结果:
thread:qthread#0,id:3,obj:0,sleep:1207
thread:qthread#2,id:5,obj:3,sleep:2454
thread:qthread#1,id:4,obj:1,sleep:1239
thread:qthread#3,id:6,obj:2,sleep:1183
thread:qthread#3,id:6,obj:2..........ok!
thread:qthread#3,id:6,obj:4,sleep:2779
thread:qthread#0,id:3,obj:0..........ok!
thread:qthread#0,id:3,obj:5,sleep:2182
thread:qthread#1,id:4,obj:1..........ok!
thread:qthread#1,id:4,obj:6,sleep:3887
thread:qthread#2,id:5,obj:3..........ok!
thread:qthread#2,id:5,obj:7,sleep:2473
thread:qthread#0,id:3,obj:5..........ok!
thread:qthread#0,id:3,obj:8,sleep:1297
thread:qthread#3,id:6,obj:4..........ok!
thread:qthread#3,id:6,obj:9,sleep:3133
thread:qthread#0,id:3,obj:8..........ok!
thread:qthread#2,id:5,obj:7..........ok!
thread:qthread#1,id:4,obj:6..........ok!
thread:qthread#3,id:6,obj:9..........ok!
非常感谢!我马上测试学习一下 --------------------编程问答-------------------- 如果你想开count个线程,那你至少有个变量记录哪count个线程正在运行,这样就知道谁跑完了,后面的可以补上。
补充:.NET技术 , C#