C#多线程操作的一个问题

xjw163 2013-12-07 07:47:42
在窗体上有一个listbox,用户可以向里面拖入文件,现在假设用户拖入了4个文件,
点击了开始按钮,
现在为了提高速度节省时间,想同时对这个4个文件进行处理,我知道如何创建线程,但暂时想不出如何同时开4个线程。


private void button1_Click(object sender, EventArgs e)
{
Thread Th1 = new Thread(showForm2);
for (int i = 0; i < listBox1.Items.Count; i++)
{
Th1.Start(listBox1.Items[i]);
}
}

public void showForm2(object o)
{
//处理代码
}


我目前的知识水平能想到的办法就是


private void button1_Click(object sender, EventArgs e)
{
Thread Th1 = new Thread(showForm2);
Thread Th2 = new Thread(showForm2);
Thread Th3 = new Thread(showForm2);
Thread Th4 = new Thread(showForm2);
Th1.Start(listBox1.Items[0].ToString());
Th1.Start(listBox1.Items[1].ToString());
Th1.Start(listBox1.Items[2].ToString());
Th1.Start(listBox1.Items[3].ToString());
}

这种办法虽然可以运行,但如果想同时开线程处理10个,100个就不可行了,求指教如何多开线程处理listbox中拖入的文件,谢谢!
...全文
326 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
xjw163 2013-12-09
  • 打赏
  • 举报
回复
引用 19 楼 sammy_luo 的回复:
[quote=引用 18 楼 xjw163 的回复:] [quote=引用 17 楼 sammy_luo 的回复:] [quote=引用 13 楼 bf6543 的回复:] 什么叫不见了?

for (int i = 0; i < listBox1.Items.Count; i++)
{
   Thread Th1 = new Thread(showForm2);
   Th1.Name = i.ToString();
   Th1.Start(listBox1.Items[i]);
}

public void showForm2(object o)
{
  MessageBox.Show(Thread.CurrentThread.Name);
}
这代码应该有问题的Thread Th1 = new Thread(showForm2);这句 你的showForm2方法是带有一个参数的,而Thread需要的一是个无参数的委托! 你确定你这样写没错?[/quote]没错,我试过了,参数可以穿进去的。[/quote] 是没错,我不明白为何object 的形参就没错,其它类型就出错!这个我没深究过, 你现在知道如何解决这问题了吗[/quote]
引用 5 楼 sp1234 的回复:
如果你不想一下子开count个,那么你就别写 i<listBox1.Items.Count 呗。
自己研究出了C#如何控制线程数量的办法了。。。分享一下吧

namespace test多线程
{
    public partial class Form1 : Form
    {
        public Queue<string> todoList = new Queue<string>();
        public const int maxRunningThread = 1;
        public int ThreadCount = 0;

        public Form1()
        {
            InitializeComponent();
        }

        public void showForm2(object o)
        {
            
            //处理
            MessageBox.Show(o.ToString());
            ThreadCount--;

            
        }

        private void button2_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < listBox1.Items.Count; i++)
            {
                todoList.Enqueue(listBox1.Items[i].ToString());
            }
            while (true)
            {
                while ((todoList.Count > 0) && (ThreadCount < maxRunningThread))
                {
                    ThreadCount++;
                    Thread Th1 = new Thread(showForm2);
                    Th1.Name = todoList.Dequeue();
                    Th1.Start(Th1.Name.ToString());
                }
                if (todoList.Count == 0)
                    break;
            }

        }
    }
}

缺点是在线程没有处理完之前,while(true)会不停的运行,也是比较好资源的,各位版主请指导个更好的办法。。。。。。
xjw163 2013-12-07
  • 打赏
  • 举报
回复
引用 19 楼 sammy_luo 的回复:
[quote=引用 18 楼 xjw163 的回复:] [quote=引用 17 楼 sammy_luo 的回复:] [quote=引用 13 楼 bf6543 的回复:] 什么叫不见了?

for (int i = 0; i < listBox1.Items.Count; i++)
{
   Thread Th1 = new Thread(showForm2);
   Th1.Name = i.ToString();
   Th1.Start(listBox1.Items[i]);
}

public void showForm2(object o)
{
  MessageBox.Show(Thread.CurrentThread.Name);
}
这代码应该有问题的Thread Th1 = new Thread(showForm2);这句 你的showForm2方法是带有一个参数的,而Thread需要的一是个无参数的委托! 你确定你这样写没错?[/quote]没错,我试过了,参数可以穿进去的。[/quote] 是没错,我不明白为何object 的形参就没错,其它类型就出错!这个我没深究过, 你现在知道如何解决这问题了吗[/quote] 现在知道了,新问题是如何控制线程的数量,这样for的话一下子就全部处理了,占用太大,我希望能控制程序同时只处理4个。 http://bbs.csdn.net/topics/390663313 您能帮忙看看吗?
  • 打赏
  • 举报
回复
引用 18 楼 xjw163 的回复:
[quote=引用 17 楼 sammy_luo 的回复:] [quote=引用 13 楼 bf6543 的回复:] 什么叫不见了?

for (int i = 0; i < listBox1.Items.Count; i++)
{
   Thread Th1 = new Thread(showForm2);
   Th1.Name = i.ToString();
   Th1.Start(listBox1.Items[i]);
}

public void showForm2(object o)
{
  MessageBox.Show(Thread.CurrentThread.Name);
}
这代码应该有问题的Thread Th1 = new Thread(showForm2);这句 你的showForm2方法是带有一个参数的,而Thread需要的一是个无参数的委托! 你确定你这样写没错?[/quote]没错,我试过了,参数可以穿进去的。[/quote] 是没错,我不明白为何object 的形参就没错,其它类型就出错!这个我没深究过, 你现在知道如何解决这问题了吗
xjw163 2013-12-07
  • 打赏
  • 举报
回复
引用 17 楼 sammy_luo 的回复:
[quote=引用 13 楼 bf6543 的回复:] 什么叫不见了?

for (int i = 0; i < listBox1.Items.Count; i++)
{
   Thread Th1 = new Thread(showForm2);
   Th1.Name = i.ToString();
   Th1.Start(listBox1.Items[i]);
}

public void showForm2(object o)
{
  MessageBox.Show(Thread.CurrentThread.Name);
}
这代码应该有问题的Thread Th1 = new Thread(showForm2);这句 你的showForm2方法是带有一个参数的,而Thread需要的一是个无参数的委托! 你确定你这样写没错?[/quote]没错,我试过了,参数可以穿进去的。
  • 打赏
  • 举报
回复
引用 13 楼 bf6543 的回复:
什么叫不见了?

for (int i = 0; i < listBox1.Items.Count; i++)
{
   Thread Th1 = new Thread(showForm2);
   Th1.Name = i.ToString();
   Th1.Start(listBox1.Items[i]);
}

public void showForm2(object o)
{
  MessageBox.Show(Thread.CurrentThread.Name);
}
这代码应该有问题的Thread Th1 = new Thread(showForm2);这句 你的showForm2方法是带有一个参数的,而Thread需要的一是个无参数的委托! 你确定你这样写没错?
  • 打赏
  • 举报
回复
引用 14 楼 xjw163 的回复:
[quote=引用 12 楼 sammy_luo 的回复:] 可以用线程池来做,假设一个池中有三个线程,你拖进来的文件保存在一个文件集合里了,你用这三个线程去去处理文件集合里的文件,处理完一个就把文件标记为已处理或者删除! 那么这三个线程干完第一个文件又会去干第二个文件,直到把你文件集合干完为止! 多线程操作时候最好把你文件集合lock住!
我这个应该不会,我不是遍历listbox的,而是将当前要处理的那个文件的路径作为参数传进线程,应该不会出什么错吧?[/quote]

        List<FileInfo> fileList = new List<FileInfo>();//假设里面有文件
        List<FileInfo> result = new List<FileInfo>();//用于保存处理后的文件

       for (int i = 0; i < listBox1.Items.Count; i++)
       {
         Thread thread = new Thread(new ThreadStart(Work));
         thread.Name = Convert.ToString(i);
         thread.Start();
       }

        public void Work()
        {
            lock (typeof(Thread))
            {
                if(result.Count<fileList.Count)
                {
                    foreach (var item in fileList)
                    {
                        //处理文件
                        if()//如果当前文件被处理
                        {
                            result.Add(item);
                        
                        }
                    }
                }
            }
        }





xjw163 2013-12-07
  • 打赏
  • 举报
回复
引用 9 楼 sp1234 的回复:
[quote=引用 5 楼 xjw163 的回复:] [quote=引用 2 楼 sp1234 的回复:] for (int i = 0; i < listBox1.Items.Count; i++) { Thread Th1 = new Thread(showForm2); Th1.Start(listBox1.Items[i]); }
隐隐约约觉得这样会内存泄漏。。。好像当new第二个Th1的时候,第一个Th1不见了。。。不知道我觉得对不对[/quote] 对的。你可以自己测试,然后循序渐进。当你发现i作为循环变量有问题,你就可以改为(例如)
var j = i;
Th1.Start(listBox1.Items[j]);
总之,程序改进,往往仅需要改动一条语句。我的习惯是不到必要的时候不多说也不多做。[/quote] 能否再进阶的提示一下有何不妥之处?多谢!
xjw163 2013-12-07
  • 打赏
  • 举报
回复
引用 12 楼 sammy_luo 的回复:
可以用线程池来做,假设一个池中有三个线程,你拖进来的文件保存在一个文件集合里了,你用这三个线程去去处理文件集合里的文件,处理完一个就把文件标记为已处理或者删除! 那么这三个线程干完第一个文件又会去干第二个文件,直到把你文件集合干完为止! 多线程操作时候最好把你文件集合lock住!
我这个应该不会,我不是遍历listbox的,而是将当前要处理的那个文件的路径作为参数传进线程,应该不会出什么错吧?
bu_ge 2013-12-07
  • 打赏
  • 举报
回复
什么叫不见了?

for (int i = 0; i < listBox1.Items.Count; i++)
{
   Thread Th1 = new Thread(showForm2);
   Th1.Name = i.ToString();
   Th1.Start(listBox1.Items[i]);
}

public void showForm2(object o)
{
  MessageBox.Show(Thread.CurrentThread.Name);
}
  • 打赏
  • 举报
回复
可以用线程池来做,假设一个池中有三个线程,你拖进来的文件保存在一个文件集合里了,你用这三个线程去去处理文件集合里的文件,处理完一个就把文件标记为已处理或者删除! 那么这三个线程干完第一个文件又会去干第二个文件,直到把你文件集合干完为止! 多线程操作时候最好把你文件集合lock住!
xjw163 2013-12-07
  • 打赏
  • 举报
回复
引用 10 楼 sp1234 的回复:
实际上你说“th1不见了”,你就没有接触到“循环变量i有问题”的这个bug。我上面的回复还是太早,应该等你明确地看到多线程处理、但是参数o有问题时才告诉你这个。
受益匪浅,我还需要多学习多思考
  • 打赏
  • 举报
回复
实际上你说“th1不见了”,你就没有接触到“循环变量i有问题”的这个bug。我上面的回复还是太早,应该等你明确地看到多线程处理、但是参数o有问题时才告诉你这个。
  • 打赏
  • 举报
回复
引用 5 楼 xjw163 的回复:
[quote=引用 2 楼 sp1234 的回复:] for (int i = 0; i < listBox1.Items.Count; i++) { Thread Th1 = new Thread(showForm2); Th1.Start(listBox1.Items[i]); }
隐隐约约觉得这样会内存泄漏。。。好像当new第二个Th1的时候,第一个Th1不见了。。。不知道我觉得对不对[/quote] 对的。你可以自己测试,然后循序渐进。当你发现i作为循环变量有问题,你就可以改为(例如)
var j = i;
Th1.Start(listBox1.Items[j]);
总之,程序改进,往往仅需要改动一条语句。我的习惯是不到必要的时候不多说也不多做。
bu_ge 2013-12-07
  • 打赏
  • 举报
回复
线程运行完会自动终止; 剩下的事情,GC会负责的;
xjw163 2013-12-07
  • 打赏
  • 举报
回复
引用 6 楼 bf6543 的回复:
把Thread Th1 = new Thread(showForm2);放到循环体里啊;每循环一次都新创建一个线程,而你现在是每次循环启动线程而已;始终都是在操作同一个线程;
隐隐约约觉得这样会内存泄漏。。。好像当new第二个Th1的时候,第一个Th1不见了。。。不知道我觉得对不对
bu_ge 2013-12-07
  • 打赏
  • 举报
回复
把Thread Th1 = new Thread(showForm2);放到循环体里啊;每循环一次都新创建一个线程,而你现在是每次循环启动线程而已;始终都是在操作同一个线程;
xjw163 2013-12-07
  • 打赏
  • 举报
回复
引用 2 楼 sp1234 的回复:
for (int i = 0; i < listBox1.Items.Count; i++) { Thread Th1 = new Thread(showForm2); Th1.Start(listBox1.Items[i]); }
隐隐约约觉得这样会内存泄漏。。。好像当new第二个Th1的时候,第一个Th1不见了。。。不知道我觉得对不对
xjw163 2013-12-07
  • 打赏
  • 举报
回复
引用 2 楼 sp1234 的回复:
for (int i = 0; i < listBox1.Items.Count; i++) { Thread Th1 = new Thread(showForm2); Th1.Start(listBox1.Items[i]); }
它们运行完了会自动结束是吗?还是要自己加一句Th1.close()或Th1.end()之类的?
  • 打赏
  • 举报
回复
。。。我觉得你都写出来了啊。。。把创建线程的语句放到循环里不就行了,然后在创建下面紧接着设置isBackground、Start什么的不就可以了?
  • 打赏
  • 举报
回复
for (int i = 0; i < listBox1.Items.Count; i++) { Thread Th1 = new Thread(showForm2); Th1.Start(listBox1.Items[i]); }
加载更多回复(1)

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧