【发布时间】:2012-12-06 15:04:12
【问题描述】:
我正在尝试结合使用TaskFactory.FromAsync 创建一个任务管道/有序调度程序。
我希望能够触发 Web 服务请求(使用 FromAsync 来使用 I/O 完成端口)但保持它们的顺序并且在任何时候只执行一个。
目前我不使用FromAsync,所以我可以使用TaskFactory.StartNew(()=>api.DoSyncWebServiceCall()),并依靠TaskFactory 使用的OrderedTaskScheduler 来确保只有一个请求未完成。
我认为在使用 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
)
但是文档说:
TaskScheduler 用于调度执行 end 方法的任务。
如您所见,它需要已经构建的IAsyncResult,而不是Func<IAsyncResult>。
这需要自定义FromAsync 方法还是我遗漏了什么?任何人都可以建议从哪里开始实施此实施吗?
干杯,
编辑:
我想从调用者那里抽象出这种行为,因此,根据TaskFactory(带有专门的TaskScheduler)的行为,我需要立即返回任务——这个任务不仅会封装@987654339 @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 调用发生时使用一个线程。理想情况下,我不必这样做。
【问题讨论】:
标签: c# .net parallel-processing task-parallel-library