我正在尝试结合 using 创建一个任务管道/有序调度程序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 调用)。
有一个重载FromAsync需要一个TaskScheduler:
public Task FromAsync(
IAsyncResult asyncResult,
Action<IAsyncResult> endMethod,
TaskCreationOptions creationOptions,
TaskScheduler scheduler
)
但文档说:
用于调度执行 end 方法的任务的 TaskScheduler。
正如您所看到的,它需要已经构建的IAsyncResult,而不是Func<IAsyncResult>.
这需要自定义FromAsync方法还是我错过了什么?谁能建议从哪里开始这个实现?
干杯,
编辑:
我想从调用者那里抽象出这种行为,因此,根据TaskFactory(使用专门的TaskScheduler)的行为,我需要立即返回 Task - 这个 Task 不仅会封装FromAsyncTask,还会在等待时封装该任务的队列轮到执行了。
一种可能的解决方案:
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但是,这会在调用发生时使用线程。理想情况下,我不必这样做。