如何创建一个调度,从来没有在同一时间使用异步执行的await多个任务? [英] How do I create a scheduler which never executes more than one Task at a time using async-await?

查看:229
本文介绍了如何创建一个调度,从来没有在同一时间使用异步执行的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 Taskclass 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请在.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 Actions (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 coordinates Tasks that are queued to its schedulers. A second instance of ConcurrentExclusiveSchedulerPair 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 same TaskScheduler that started it. So this means if one async method calls another async method, the "child" method will "inherit" the parent's TaskScheduler. Any async method may opt out of continuing on its TaskScheduler by using ConfigureAwait(false) (in that case, it continues directly on the thread pool).

这篇关于如何创建一个调度,从来没有在同一时间使用异步执行的await多个任务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆