并发受限的 TaskScheduler 会阻塞自身

TaskScheduler with limited concurrency blocks itself

我正在尝试使用 the following custom task scheduler 来限制并发网络请求:

我是这样使用的:

const int CONCURRENCY_LEVEL = 2;

static void Main()
{
    TaskFactory factory = new TaskFactory(new LimitedConcurrencyLevelTaskScheduler(CONCURRENCY_LEVEL));

    Task.WaitAll(new[] { factory.StartNew(() => SomeAction("first")), factory.StartNew(() => SomeAction("second")) });

    Console.WriteLine("All tasks ended");        
    Console.Read();
}

static void SomeAction(string task)
{
    Console.WriteLine(task + " task started");
    Console.WriteLine(AnotherTask(task).Result);
    Console.WriteLine(task + " task ended");
}

static async Task<string> AnotherTask(string task)
{
    return await Task.Run(() =>
    {
        Console.WriteLine(task + " inner task started");
        // imitate web requests
        Thread.Sleep(200);
        Console.WriteLine(task + " inner task ended");
        return "ok";
    });
}

问题是内部任务正在使用我的 LimitedConcurrencyLevelTaskScheduler 而不是默认的 TaskScheduler。这导致自我阻塞,输出是这样的:

second task started
first task started
first inner task started
second inner task started
second inner task ended
first inner task ended

当我将 CONCURRENCY_LEVEL 更改为 3 或将 factory 更改为 Task.Factory 时,显然一切正常,输出如下:

first task started
second task started
first inner task started
second inner task started
second inner task ended
first inner task ended
ok
second task ended
ok
first task ended
All tasks ended

无法更改SomeAction中的代码。我还可以做些什么? Microsoft 示例中是否存在错误?

尝试

static async Task<string> AnotherTask(string task)
{
    return await Task.Run(() =>
    {
        Console.WriteLine(task + " inner task started");
        // imitate web requests
        Thread.Sleep(200);
        Console.WriteLine(task + " inner task ended");
        return "ok";
    }).ConfigureAwait(false); //<--------
}

从自定义任务计划程序启动任务时指定 TaskCreationOptions.HideScheduler

Task.WaitAll(new[] 
{
   factory.StartNew(() => SomeAction("first"),  TaskCreationOptions.HideScheduler), 
   factory.StartNew(() => SomeAction("second"), TaskCreationOptions.HideScheduler)
});

来自MSDN

HideScheduler Prevents the ambient scheduler from being seen as the current scheduler in the created task. This means that operations like StartNew or ContinueWith that are performed in the created task will see Default as the current scheduler.