我有一个场景,我需要根据可配置变量动态创建线程数。我一次只能启动该数量的线程,一旦完成其中一个线程,我需要分配一个与队列中相同线程的方法。
任何人都可以通过示例帮我解决上述情况。
我已经研究了一个星期但没能得到具体的解决方案。
答案 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.Pulse和Monitor.Wait等
正如我所说,async/await
可能会带来更好的解决方案,但你明确要求线程。