我正在尝试结合使用 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
)
但是文档说:
The TaskScheduler that is used to schedule the task that executes the end method.
如您所见,它需要已经构建好的 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 操作。启动这些 IO 不涉及托管代码,TaskScheduler
类不会发挥作用。
因此,您必须延迟启动 IO,直到您确定确实希望网络受到攻击。您可以使用 SemaphoreSlim.WaitAsync
来限制当前运行的任务数量。在启动单个 IO 之前等待该方法的结果并等待它。
关于c# - TPL FromAsync 与 TaskScheduler 和 TaskFactory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13746421/