当前位置:编程学习 > C#/ASP.NET >>

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>();
for (int i = 0; i < listBox1.Items.Count; i++)
{
    tsks.Add(new Task(()=>showForm2(listBox1.Items[i])));
}
Task.WaitAll(tsks.ToArray());
--------------------编程问答-------------------- 那么你可以使用ThreadPool类。 --------------------编程问答-------------------- 使用线程对象的Aborted属性判断线程是否结束 --------------------编程问答-------------------- 如果你不想一下子开count个,那么你就别写 i<listBox1.Items.Count 呗。 --------------------编程问答--------------------
引用 2 楼 sp1234 的回复:
如果你的 showForm2 方法原本就是一个顺序执行的方法,那么可以写
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());

是的,是一个图片处理的程序,中间有for,while等循环,但一定会执行完的 --------------------编程问答-------------------- 好像没有解决问题的答案。。。顶上去 --------------------编程问答--------------------
引用 5 楼 sp1234 的回复:
如果你不想一下子开count个,那么你就别写 i<listBox1.Items.Count 呗。
一开始第一个想到的办法就是这个,完了才想到要控制线程的数量,毕竟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.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我之前还真没用过,现学现卖,上面的代码我测过了,没问题,应该可以符合你的需求

ThreadPool.SetMaxThreads(4, 4);

但是这两个参数我还没完全理解 --------------------编程问答--------------------
引用 10 楼 bf6543 的回复:
ThreadPool我之前还真没用过,现学现卖,上面的代码我测过了,没问题,应该可以符合你的需求

ThreadPool.SetMaxThreads(4, 4);

但是这两个参数我还没完全理解


感谢,经过测试,完全达到要求

没错,目前我的水平暂时就是这样了,遇到问题就实时求助,然后拼接进自己的代码。。。。希望有天自己也能成为高手。。。 --------------------编程问答--------------------
引用 10 楼 bf6543 的回复:
ThreadPool我之前还真没用过,现学现卖,上面的代码我测过了,没问题,应该可以符合你的需求

ThreadPool.SetMaxThreads(4, 4);

但是这两个参数我还没完全理解

我也无法理解,我试着修改参数4,4 发现比如修改为3,1的时候,还是会执行所有的线程。。。 --------------------编程问答--------------------
引用 11 楼 xjw163 的回复:
Quote: 引用 10 楼 bf6543 的回复:

ThreadPool我之前还真没用过,现学现卖,上面的代码我测过了,没问题,应该可以符合你的需求

ThreadPool.SetMaxThreads(4, 4);

但是这两个参数我还没完全理解


感谢,经过测试,完全达到要求

没错,目前我的水平暂时就是这样了,遇到问题就实时求助,然后拼接进自己的代码。。。。希望有天自己也能成为高手。。。
又试了下,还是不够理想啊,貌似只有设置为4以上的数时才有效,低于4就不受控制了。。。怎么回事呢 --------------------编程问答--------------------
引用 11 楼 xjw163 的回复:
Quote: 引用 10 楼 bf6543 的回复:

ThreadPool我之前还真没用过,现学现卖,上面的代码我测过了,没问题,应该可以符合你的需求

ThreadPool.SetMaxThreads(4, 4);

但是这两个参数我还没完全理解


感谢,经过测试,完全达到要求

没错,目前我的水平暂时就是这样了,遇到问题就实时求助,然后拼接进自己的代码。。。。希望有天自己也能成为高手。。。

我现在有时间就到csdn看看,看到别人的问题,会的我就说说,不会而且有价值我就收藏了,坐等大神的答案,能学到不少东西。慢慢学吧~共勉啊~ --------------------编程问答--------------------
引用 14 楼 bf6543 的回复:
Quote: 引用 11 楼 xjw163 的回复:

Quote: 引用 10 楼 bf6543 的回复:

ThreadPool我之前还真没用过,现学现卖,上面的代码我测过了,没问题,应该可以符合你的需求

ThreadPool.SetMaxThreads(4, 4);

但是这两个参数我还没完全理解


感谢,经过测试,完全达到要求

没错,目前我的水平暂时就是这样了,遇到问题就实时求助,然后拼接进自己的代码。。。。希望有天自己也能成为高手。。。

我现在有时间就到csdn看看,看到别人的问题,会的我就说说,不会而且有价值我就收藏了,坐等大神的答案,能学到不少东西。慢慢学吧~共勉啊~


关于我的问题我想到了一个间接的办法,那就是预估线程需要执行的时间,等到了一定的时间再开新线程,比如,我测试一个线程处理数据需要10分钟,我就等12分钟再开新线程,不过这样虽然可以,就是太不科学了,CPU利用率也不高,顶多是替代了手工操作而已了。坐等高手的答案吧。。。 --------------------编程问答-------------------- 那没必要了,ThreadPool就是把所有的线程加入等待队列,比如目前最大4个进程,有一个结束的时候,马上就会启动下一个; --------------------编程问答--------------------
引用 13 楼 xjw163 的回复:
Quote: 引用 11 楼 xjw163 的回复:

Quote: 引用 10 楼 bf6543 的回复:

ThreadPool我之前还真没用过,现学现卖,上面的代码我测过了,没问题,应该可以符合你的需求

ThreadPool.SetMaxThreads(4, 4);

但是这两个参数我还没完全理解


感谢,经过测试,完全达到要求

没错,目前我的水平暂时就是这样了,遇到问题就实时求助,然后拼接进自己的代码。。。。希望有天自己也能成为高手。。。
又试了下,还是不够理想啊,貌似只有设置为4以上的数时才有效,低于4就不受控制了。。。怎么回事呢

你是四核电脑吧
不能将辅助线程的数目或 I/O 完成线程的数目设置为小于计算机的处理器数目 --------------------编程问答--------------------
引用 17 楼 bf6543 的回复:
Quote: 引用 13 楼 xjw163 的回复:

Quote: 引用 11 楼 xjw163 的回复:

Quote: 引用 10 楼 bf6543 的回复:

ThreadPool我之前还真没用过,现学现卖,上面的代码我测过了,没问题,应该可以符合你的需求

ThreadPool.SetMaxThreads(4, 4);

但是这两个参数我还没完全理解


感谢,经过测试,完全达到要求

没错,目前我的水平暂时就是这样了,遇到问题就实时求助,然后拼接进自己的代码。。。。希望有天自己也能成为高手。。。
又试了下,还是不够理想啊,貌似只有设置为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!
--------------------编程问答--------------------
引用 23 楼 btman52 的回复:
使用多线程+线程安全队列,将所有的任务抽象为一个过程+为过程提供的对象,即委托+参数
记事本写的代码,排版乱了见谅

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#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,