我正试图结合使用TaskFactory.FromAsync
创建一个任务管道/有序调度程序。
我希望能够触发web服务请求(使用FromAsync
来使用i/o完成端口),但要保持它们的顺序,并且在任何时候都只能执行一个请求。
目前我不使用FromAsync
所以我可以使用TaskFactory.StartNew(()=>api.DoSyncWebServiceCall())
并依赖OrderedTaskScheduler
使用的TaskFactory
来确保只有一个请求未完成。
我假设在使用FromAsync
方法时这种行为会保持不变,但它不会:
TaskFactory<Stuff> taskFactory = new TaskFactory<Stuff>(new OrderedTaskScheduler());
var t1 = taskFactory.FromAsync((a, s) => api.beginGetStuff(a, s), a => api.endGetStuff(a));
var t2 = taskFactory.FromAsync((a, s) => api.beginGetStuff(a, s), a => api.endGetStuff(a));
var t3 = taskFactory.FromAsync((a, s) => api.beginGetStuff(a, s), a => api.endGetStuff(a));
所有这些
beginGetStuff
方法都是在FromAsync
调用中调用的(因此尽管它们是按顺序调度的,但同时也有n
api调用)。有一个带taskscheduler的重载
FromAsync
:public Task FromAsync(
IAsyncResult asyncResult,
Action<IAsyncResult> endMethod,
TaskCreationOptions creationOptions,
TaskScheduler scheduler
)
但是医生说:
用于调度执行End方法的任务的任务计划程序。
如您所见,它接受已经构造的
IAsyncResult
,而不是Func<IAsyncResult>
。这需要一个自定义的
FromAsync
方法,还是我遗漏了什么?有人能建议从哪里开始实施这个计划吗?干杯,
编辑:
我想把这个行为从调用者那里抽象出来,因此,根据
TaskFactory
的行为(使用一个专门的TaskScheduler
),我需要立即返回任务-这个任务不仅封装了FromAsync
任务,而且还将在等待执行的时候对该任务进行排队。一种可能的解决方案:
class TaskExecutionQueue
{
private readonly OrderedTaskScheduler _orderedTaskScheduler;
private readonly TaskFactory _taskFactory;
public TaskExecutionQueue(OrderedTaskScheduler orderedTaskScheduler)
{
_orderedTaskScheduler = orderedTaskScheduler;
_taskFactory = new TaskFactory(orderedTaskScheduler);
}
public Task<TResult> QueueTask<TResult>(Func<Task<TResult>> taskGenerator)
{
return _taskFactory.StartNew(taskGenerator).Unwrap();
}
}
然而,这在发生
FromAsync
调用时使用线程。理想情况下我不必那样做。 最佳答案
无法计划IO任务,因为它们没有与之关联的线程。Windows内核提供无线程IO操作。启动这些ios不涉及托管代码,TaskScheduler
类也不起作用。
所以你必须延迟启动IO,直到你真的想让网络受到攻击。您可以使用SemaphoreSlim.WaitAsync
来限制当前运行的任务量。在启动单个IO之前等待该方法的结果,并等待该结果。