如何创建一个调度,从来没有在同一时间使用异步执行的await多个任务? [英] How do I create a scheduler which never executes more than one Task at a time using async-await?
问题描述
我想实现一个确保,我从来没有在同一时间为一组特定的操作(HTTP调用)的执行多个任务的类或图案。任务的调用可以在随机时间来自不同的线程。我想利用异步等待模式,以便调用者可以通过包装在一个try-catch呼叫处理异常。
I want to implement a class or pattern that ensures that I never execute more than one Task at a time for a certain set of operations (HTTP calls). The invocations of the Tasks can come from different threads at random times. I want to make use of the async-await pattern so that the caller can handle exceptions by wrapping the call in a try-catch.
下面是执行的预定流程说明:
Here's an illustration of the intended flow of execution:
从主叫伪code:
try {
Task someTask = GetTask();
await SomeScheduler.ThrottledRun(someTask);
}
catch(Exception ex) {
// Handle exception
}
这里的工作
类可能反而会因解决方案的动作
类。
The Task
class here might instead be an Action
class depending on the solution.
请注意,我在我,我不一定用它关系到的。NET任务计划程序。我不知道异步等待库不够好,知道在什么角度,用什么工具来解决这个问题。该的TaskScheduler可能与此有关,也可能没有。我读过抽头模式文件发现,几乎解决了这个问题的模式,但并不完全(上交织章)。
Note that I when I use the word "Schedule" in this question I'm not necessarily using it with relation to the .NET Task Scheduler. I don't know the async-await library well enough to know at what angle and with what tools to approach this problem. The TaskScheduler might be relevant here, and it may not. I've read the TAP pattern document and found patterns that almost solve this problem, but not quite (the chapter on interleaving).
推荐答案
有一个新的<一个href=\"http://msdn.microsoft.com/en-us/library/system.threading.tasks.concurrentexclusiveschedulerpair%28v=VS.110%29.aspx\"><$c$c>ConcurrentExclusiveSchedulerPair$c$c>请在.NET 4.5(我不记得,如果它被列入异步CTP),你可以使用它的 ExclusiveScheduler
来限制执行一个任务
一次。
There is a new ConcurrentExclusiveSchedulerPair
type in .NET 4.5 (I don't remember if it was included in the Async CTP), and you can use its ExclusiveScheduler
to restrict execution to one Task
at a time.
考虑结构化您的问题作为数据流。它很容易只通过一个的TaskScheduler
成你想要限制数据流的部分块的选项。
Consider structuring your problem as a Dataflow. It's easy to just pass a TaskScheduler
into the block options for the parts of the dataflow you want restricted.
如果您不想(或不能)使用数据流,你可以做类似的事情自己。请记住,在TAP,你总是回到开始的任务,所以您不必创造,从调度分开就像你在做第三方物流
If you don't want to (or can't) use Dataflow, you can do something similar yourself. Remember that in TAP, you always return started tasks, so you don't have the "creation" separated from the "scheduling" like you do in TPL.
您可以使用 ConcurrentExclusiveSchedulerPair </ code>安排
动作
S(或异步
lambda表达式没有返回值)是这样的:
You can use ConcurrentExclusiveSchedulerPair
to schedule Action
s (or async
lambdas without return values) like this:
public static ConcurrentExclusiveSchedulerPair schedulerPair =
new ConcurrentExclusiveSchedulerPair();
public static TaskFactory exclusiveTaskFactory =
new TaskFactory(schedulerPair.ExclusiveScheduler);
...
public static Task RunExclusively(Action action)
{
return exclusiveTaskFactory.StartNew(action);
}
public static Task RunExclusively(Func<Task> action)
{
return exclusiveTaskFactory.StartNew(action).Unwrap();
}
有几件事情要注意一下:
There are a few things to note about this:
-
的单个实例ConcurrentExclusiveSchedulerPair </ code>只坐标
工作
秒。ConcurrentExclusiveSchedulerPair </ code>的第二个实例是独立于第一,所以你必须保证同一个实例是您要协调你的系统的所有部件。
- 的
异步
方法 - 默认情况下 - 在相同的简历的TaskScheduler
启动它。因此,这意味着,如果一个异步
方法调用另一个异步
法,儿童的方法将继承了父母的的TaskScheduler
。任何异步
方法可以选择不继续在其的TaskScheduler
通过使用ConfigureAwait(假)
(在这种情况下,它直接地继续在线程池)。
正在排队的调度
- A single instance of
ConcurrentExclusiveSchedulerPair
only coordinatesTask
s that are queued to its schedulers. A second instance ofConcurrentExclusiveSchedulerPair
would be independent from the first, so you have to ensure the same instance is used in all parts of your system you want coordinated. - An
async
method will - by default - resume on the sameTaskScheduler
that started it. So this means if oneasync
method calls anotherasync
method, the "child" method will "inherit" the parent'sTaskScheduler
. Anyasync
method may opt out of continuing on itsTaskScheduler
by usingConfigureAwait(false)
(in that case, it continues directly on the thread pool).
这篇关于如何创建一个调度,从来没有在同一时间使用异步执行的await多个任务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!