在审查了这个论坛上的很多帖子以及其他关于c#多线程的帖子后,我仍然感到困惑,并且在处理手头的问题时遇到了问题。
我想创建numThreads
个线程来为documentIds
中的每个整数执行一个函数。 documentIds
是一个List<int>
,其Count = 100,我想在documentIds
中的每个元素上调用RestitchWorker.Restitch。
我目前的情况如下,但我对于如何保持5个线程以及在100个documentIds列表中循环感到困惑...所有帮助都表示赞赏。
for (int i = 0; i < documentIds.Count; i++)
{
if (threadCount < numThreads)
{
var Worker = new RestitchWorker(documentIds.ElementAt(i));
Thread t_restitchWorker = new Thread(() => Worker.Restitch());
threadCount++;
t_restitchWorker.Start();
t_restitchWorker.Join();
}
}
答案 0 :(得分:5)
这个问题确实更适合于任务而非线程。如果你的问题明确地创建线程是没有必要的;然后线程池可以更高效,因为线程管理可能很昂贵。
任务适合需要松散地并行实现100个长作业的问题,因为它们将汇集线程而不是创建100个显式线程,并且具有支持等待多个任务的易于使用的API。
任务列表
您可以通过创建任务列表并调用System.Threading.Tasks.Task.WaitAll
来执行此操作:
var tasks = new List<Task>();
for (int i = 0; i < n; ++i)
{
tasks.Add(Task.Run(action: SomeLongTask));
}
Task.WaitAll(tasks);
<强>的Parallel.For 强>
然而,更好的方法是这样做,因为它在for循环中你需要传递一个整数就是使用System.Threading.Tasks.Parallel.For
:
Parallel.For(0, n, (i) =>
{
SomeLongTask(i);
});
答案 1 :(得分:2)
有许多机制可以对应用程序进行多线程处理。您可以使用异步任务,任务并行库(TPL),线程池,信号量等。当我需要对我一次生成多少线程的高度控制时,我使用的机制是使用SemaphoreSlim ,设置最大线程数,然后使用Wait
等待新线程变为可用。我将我的数据(例如文档ID列表)放入ConcurrentQueue
,以便我可以安全地排队和出列我的线程需要执行工作的信息,而不必担心(太多)线程安全。异步任务可用于实际开始执行工作。
static class Program
{
private const int _maxWorkers = 10;
private static readonly SemaphoreSlim _threadManager = new SemaphoreSlim(_maxWorkers);
private void DoStuff()
{
var queue = new ConcurrentQueue<int>(SomeClass.GetDocumentIds());
var operations = new List<Task>();
while (!queue.IsEmpty)
{
int documentId;
if (queue.TryDequeue(out documentId))
{
_threadManager.Wait(); // this will block after max number of threads is met
try
{
operations.Add(GetDocument(documentId);
}
catch (Exception)
{
// ignored
}
}
}
Task.WaitAll(operations.ToArray()); // finally, this waits till the last remaining tasks are complete
}
private static async Task GetDocument(int documentId)
{
await Task.Yield();
try
{
GoGetDocument(documentId);
}
catch (Exception)
{
// ignored
}
finally
{
_threadManager.Release(); // release the semaphore when the task completes
}
}