节气门WebRequests

问题描述:

我想执行一堆WebRequest,但是设置了可以同时启动的数量的阈值.

I want to execute a bunch of WebRequests, but set a threshold on how many can be started simultaneously.

我遇到了这个

I came across this LimitedConcurrencyTaskScheduler example and tried to utilize it like so

scheduler = new LimitedConcurrencyLevelTaskScheduler(1);
taskFactory = new TaskFactory(scheduler);

...

    private Task<WebResponse> GetThrottledWebResponse(WebRequest request)
    {
        return taskFactory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null);
    }

但是,我注意到即使最大并发数为1,我的任务似乎仍以非FIFO顺序完成.当我在LimitedConcurrencyLevelTask​​Scheduler中放置断点时,很明显根本没有使用断点.我想我使用TaskFactory.FromAsync的方式并没有达到我的预期.

However I noticed that even with a max concurrency of 1, my tasks seemed to be completing in a non-FIFO order. When I put breakpoints in LimitedConcurrencyLevelTaskScheduler, it became apparent that it's not being used at all. I guess the way I'm using TaskFactory.FromAsync is not doing what I had expected.

是否有适当的方法来限制同时发出的WebRequest?

Is there a proper way to throttle simultaneous WebRequests?

当我在LimitedConcurrencyLevelTask​​Scheduler中放置断点时,很明显根本没有使用断点

When I put breakpoints in LimitedConcurrencyLevelTaskScheduler, it became apparent that it's not being used at all

那是正确的. FromAsync根本不使用TaskFactory.实际上,我不太了解为什么这种方法不是静态的.

That is correct. FromAsync doesn't use the TaskFactory at all. In fact, I don't really understand why this method isn't static.

您可以通过多种方式来实现节流.您可以使用Microsoft.Tpl.Dataflow中的ActionBlock.或者,您也可以使用SemaphoreSlim:

You have multiple ways to implement the throttling. You could use the ActionBlock From Microsoft.Tpl.Dataflow. Or you could make your own using SemaphoreSlim:

private static readonly SemaphoreSlim Semaphore = new SemaphoreSlim(1);

private static async Task<WebResponse> GetThrottledWebResponse(WebRequest request)
{
    await Semaphore.WaitAsync().ConfigureAwait(false);

    try
    {
        return await request.GetResponseAsync().ConfigureAwait(false);
    }
    finally
    {
        Semaphore.Release();
    }
}