繁体   English   中英

c#多线程问题等待线程

[英]c# multithreading issue waiting for threads

在审查了这个论坛上的很多帖子以及其他关于c#multithreading的帖子后,我仍然感到困惑,并且在处理手头的问题时遇到了问题。

我想创建numThreads线程数来为documentIds每个整数执行一个函数。 documentIds是一个List<int>以计数= 100,我想调用RestitchWorker.Restitch每个在这些元件中的documentIds

我目前的情况如下,但我很困惑如何保持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();
     }
}

这个问题确实更适合于任务而不是线程。 如果你的问题明确地创建线程是没有必要的; 然后线程池可以更高效,因为线程管理可能很昂贵。

任务适合需要松散地并行实现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); 
});

有许多用于多线程应用程序的机制。 您可以使用异步任务,任务并行库(TPL),线程池,信号量等。当我需要对我一次生成多少线程的高度控制时,我使用的机制是使用SemaphoreSlim,set最大线程数,然后使用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
            }

    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM