C# WinForms循环中的多线程

3

场景

我的应用程序中有一个后台工作线程,它会进行一系列的处理。我特意使用这种实现方式来保持用户界面流畅,并防止其冻结。我想保留后台工作线程,但在该线程内部,仅产生另外三个线程 - 让它们共享处理(目前工作线程只是循环遍历并逐个处理每个资产。但我想通过仅使用有限数量的线程来加快处理速度。

问题

给定下面的代码,如何使循环选择一个空闲的线程,如果没有空闲线程则等待,直到有空闲线程再继续。

代码

        foreach (KeyValuePair<int, LiveAsset> kvp in laToHaganise)
        {

             Haganise h = new Haganise(kvp.Value,
                                      busDate,
                                      inputMktSet,
                                      outputMktSet, 
                                      prodType,
                                      noOfAssets, 
                                      bulkSaving);

             h.DoWork();

         }

思考

我猜想我需要先创建三个新线程,但我的担忧是,如果每次我都实例化一个新的Haganise对象-如何将正确的“h”对象传递给正确的线程.....

  Thread firstThread = new Thread(new ThreadStart(h.DoWork));
  Thread secondThread =new Thread(new ThreadStart(h.DoWork));
  Thread thirdThread = new Thread(new ThreadStart(h.DoWork));

非常感谢您的帮助。


除非您正在使用导致原始线程延迟的外部资源,否则将工作分成三个或更多线程并不能保证有益。这只是一个给您的建议。 - Codesleuth
为什么要限制线程数,当你可以使用线程池呢?你尝试过并行扩展吗? - jmservera
2个回答

2
根据任务的大小,ThreadPool.QueueUserWorkItem 可能是一个不错的选择。它会创建一个线程并将其放入队列中,在池中有可用线程时执行。
或者,您可以创建自己的类型池,其中包含3个线程,并使用ManualResetEvent来确定特定线程何时完成。

1

两种可能性:

这里有一个可行的示例,它选择下一个空闲的工作者:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        private static List<MyWorker> _Workers;

        static void Main(string[] args)
        {
            _Workers = new List<MyWorker>();

            for (int i = 0; i < 5; i++)
            {
                _Workers.Add(CreateDefaultWorker(i));
            }

            StartJobs(20000);
            Console.ReadKey();
        }

        private static void StartJobs(int runtime)
        {
            Random rand = new Random();
            DateTime startTime = DateTime.Now;

            while (DateTime.Now - startTime < TimeSpan.FromMilliseconds(runtime))
            {
                var freeWorker = GetFreeWorker();

                if (freeWorker != null)
                {
                    freeWorker.Worker.RunWorkerAsync(new Action(() => DoSomething(freeWorker.Index, rand.Next(500, 2000))));
                }
                else
                {
                    Console.WriteLine("No free worker available!");
                    Console.WriteLine("Waiting for free one...");
                    WaitForFreeOne();
                }
            }
        }

        private static MyWorker GetFreeWorker()
        {
            foreach (var worker in _Workers)
            {
                if (!worker.Worker.IsBusy)
                    return worker;
            }

            return null;
        }

        private static void WaitForFreeOne()
        {
            while (true)
            {
                foreach (var worker in _Workers)
                {
                    if (!worker.Worker.IsBusy)
                        return;
                }
                Thread.Sleep(1);
            }
        }

        private static MyWorker CreateDefaultWorker(int index)
        {
            var worker = new MyWorker(index);

            worker.Worker.DoWork += (sender, e) => ((Action)e.Argument).Invoke();
            worker.Worker.RunWorkerCompleted += (sender, e) => Console.WriteLine("Job finished in worker " + worker.Index);

            return worker;
        }

        static void DoSomething(int index, int timeout)
        {
            Console.WriteLine("Worker {1} starts to work for {0} ms", timeout, index);
            Thread.Sleep(timeout);
        }
    }

    public class MyWorker
    {
        public int Index { get; private set; }
        public BackgroundWorker Worker { get; private set; }

        public MyWorker(int index)
        {
            Index = index;
            Worker = new BackgroundWorker();
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接