c# - 如何防止创建的线程多于可用的硬件线程数?

标签 c# .net multithreading task-parallel-library

我有以下方法,用于通过为每个文件创建不同的任务来初始化和启动日志文件处理。在任务管理器中,我可以看到该函数正在以这种方式创建大约一百个线程。

public async Task LogProcessing(DescriptorList files, CancellationToken ct)
{
    var tasks = new List<Task>();
    foreach (var file in files)
        tasks.Add(new Task(() =>
        {
            ParsingFile(file, ct);
        }));

    foreach (var task in tasks) { task.Start(); }
   
    await Task.WhenAll(tasks);       
}

如何防止创建的线程多于可用硬件线程数? 谢谢。

最佳答案

如果您使用 .NET 6.0 或更高版本,则可以使用 Parallel.ForEachAsync()为此:

await Parallel.ForEachAsync(
    files,
    new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct },
    async (file, cancellation) =>
    {
        await Task.Run(() => ParsingFile(file, cancellation), cancellation);
    });

请注意使用 MaxDegreeOfParallelism = Environment.ProcessorCount 将并发线程数限制为(逻辑)处理器计数。这实际上通常是默认设置,因此您可能根本不需要设置它,但为了清楚起见,有些人可能喜欢这样做。

根据文档“一般情况下,您不需要修改此设置”,但您应该查看 this answer from Theodor Zoulias在使用默认值之前。 (我自己一般不使用默认值)。

我建议阅读the documentation on MaxDegreeOfParallelism并自行决定是否指定。

根据下面 TheodorZoulias 的评论,您可以更简单地写为:

await Parallel.ForEachAsync(
    files,
    new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = cancelSource.Token },
    (file, cancellation) =>
    {
        ParsingFile(file, cancellation);
        return ValueTask.CompletedTask;
    });

但是,如果 ParsingFile() 本身就是 async,那么您当然会使用第一个版本。

关于c# - 如何防止创建的线程多于可用的硬件线程数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77374632/

相关文章:

c# - 使用 Async/Await 的无限递归调用永远不会抛出异常

c# - Protocol Buffer 消息的字节顺序

c# - 具有多态数组的 WCF 客户端调用方法失败

.net - 启动时完全隐藏WPF窗口吗?

c - 测试竞争条件

c# - 通过 Windows 窗体应用程序从 exchange online (Office 365) 读取电子邮件

c# - 我应该使用字段还是属性?

c# - 修改注册表键值

multithreading - 互斥体是否保证获取顺序?

使用 pthreads 在多线程代码中计数器值意外更改