我正在尝试结合 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 不仅会封装FromAsync
Task,还会在等待时封装该任务的队列轮到执行了。
一种可能的解决方案:
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
但是,这会在调用发生时使用线程。理想情况下,我不必这样做。