并发受限的 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.
我正在尝试使用 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 likeStartNew
orContinueWith
that are performed in the created task will seeDefault
as the current scheduler.