我正试图结合使用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调用中调用的(因此尽管它们是按顺序调度的,但同时也有napi调用)。
有一个带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之前等待该方法的结果,并等待该结果。

07-24 20:07