Task.Run如何受CPU内核的限制?

Nic*_*ams 0 c# multithreading task

为什么以下程序只运行有限数量的被阻止任务.限制数似乎是机器上的核心数.

最初,当我写这篇文章时,我希望看到以下内容:

  • 乔布斯1 - 24的工作完成输出
  • 2秒的差距
  • 工作的输出25 - 48

然而输出是:

  • 乔布斯1 - 4的工作完成输出
  • 然后每隔100ms随机完成一次工作.

当在具有32个内核的服务器上运行时,程序确实按照我的预期运行.

class Program
{
    private static object _lock = new object();
    static void Main(string[] args)
    {
        int completeJobs = 1;
        var limiter = new MyThreadLimiter();
        for (int iii = 1; iii < 100000000; iii++)
        {
            var jobId = iii;
            limiter.Schedule()
                .ContinueWith(t =>
                {
                    lock (_lock)
                    {
                        completeJobs++;
                        Console.WriteLine("Job: " + completeJobs + " scheduled");
                    }
                });
        }

        Console.ReadLine();
    }
}

class MyThreadLimiter
{
    readonly SemaphoreSlim _semaphore = new SemaphoreSlim(24);

    public async Task Schedule()
    {
        await _semaphore.WaitAsync();

        Task.Run(() => Thread.Sleep(2000))
            .ContinueWith(t => _semaphore.Release());
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,用Task.Delay替换Thread.Sleep会得到我期望的结果.

    public async Task Schedule()
    {
        await _semaphore.WaitAsync();

        Task.Delay(2000)
            .ContinueWith(t => _semaphore.Release());
    }
Run Code Online (Sandbox Code Playgroud)

使用a Thread给出了我的预期结果

    public async Task Schedule()
    {
        await _semaphore.WaitAsync();

        var thread = new Thread(() =>
        {
            Thread.Sleep(2000);
            _semaphore.Release();
        });
        thread.Start();
    }
Run Code Online (Sandbox Code Playgroud)

Task.Run()工作怎么样?它是否仅限于核心数量?

Ser*_*rvy 7

Task.Run安排工作在线程池中运行.线程池具有广泛的自由度,可以尽可能地调度工作,以便最大化吞吐量.它会在感觉有用时创建额外的线程,并且当它认为它不能为它们提供足够的工作时从池中删除线程.

当你有CPU绑定工作时,创建比处理器能够同时运行的更多线程并不会有效.添加更多线程只会导致更多的上下文切换,增加开销并降低吞吐量.