如何在C#中完成任何线程时动态创建一定数量的线程并分配方法?

时间:2015-12-17 13:43:59

标签: c# multithreading threadpool

我有一个场景,我需要根据可配置变量动态创建线程数。我一次只能启动该数量的线程,一旦完成其中一个线程,我需要分配一个与队列中相同线程的方法。

任何人都可以通过示例帮我解决上述情况。

我已经研究了一个星期但没能得到具体的解决方案。

3 个答案:

答案 0 :(得分:1)

有很多方法可以解决这个问题,但最好的方法取决于您的具体问题。

但是,假设您有一组要对其进行处理的项目,并使用单独的线程处理每个项目 - 最多可指定您指定的同时线程数。

一种非常简单的方法是通过AsParallel()WithDegreeOfParallelism()使用Plinq,如下面的控制台应用程序所示:

using System;
using System.Linq;
using System.Threading;

namespace Demo
{
    static class Program
    {
        static void Main()
        {
            int maxThreads = 4;
            var workItems = Enumerable.Range(1, 100);
            var parallelWorkItems = workItems.AsParallel().WithDegreeOfParallelism(maxThreads);

            parallelWorkItems.ForAll(worker);
        }

        static void worker(int value)
        {
            Console.WriteLine($"Worker {Thread.CurrentThread.ManagedThreadId} is processing {value}");
            Thread.Sleep(1000); // Simulate work.
        }
    }
}

如果运行此命令并检查输出,您将看到多个线程正在处理工作项,但最大线程数限制为指定值。

答案 1 :(得分:0)

你应该看一下线程池。有关详细信息,请参阅此链接Threadpooling in .NET。一旦完成一个线程中的工作,您很可能必须使用回调来完成调用方法的任务

答案 2 :(得分:0)

使用async/await可能会为您提供更智能的解决方案,具体取决于您要实现的目标。但是既然你明确地询问了线程,那么这是一个做你想要的短类:

public class MutliThreadWorker : IDisposable
{
    private readonly ConcurrentQueue<Action> _actions = new ConcurrentQueue<Action>();
    private readonly List<Thread> _threads = new List<Thread>();
    private bool _disposed;

    private void ThreadFunc()
    {
        while (true)
        {
            Action action;
            while (!_actions.TryDequeue(out action)) Thread.Sleep(100);
            action();
        }
    }
    public MutliThreadWorker(int numberOfThreads)
    {
        for (int i = 0; i < numberOfThreads; i++)
        {
            Thread t = new Thread(ThreadFunc);
            _threads.Add(t);
            t.Start();
        }
    }
    public void Dispose()
    {
        Dispose(true);
    }
    protected virtual void Dispose(bool disposing)
    {
        _disposed = true;
        foreach (Thread t in _threads)
            t.Abort();
        if (disposing)
            GC.SuppressFinalize(this);
    }
    public void Enqueue(Action action)
    {
        if (_disposed)
            throw new ObjectDisposedException("MultiThreadWorker");
        _actions.Enqueue(action);
    }

}

此类在实例化时启动所需的线程数:

int requiredThreadCount = 16; // your configured value
MultiThreadWorker mtw = new MultiThreadWorker(requiredThreadCount);

然后使用ConcurrentQueue<T>来跟踪要执行的任务。您可以通过

将方法添加到队列中
mtw.Enqueue(() => DoThisTask());

我做了IDisposable以确保踏板最终停止。 当然,这需要稍微改进,因为中止这样的线程不是最好的做法。

ThreadFunc本身会反复检查是否存在排队操作并执行它们。使用Monitor.PulseMonitor.Wait

的模式也可以稍微改善一下

正如我所说,async/await可能会带来更好的解决方案,但你明确要求线程。