限制并行运行方法的数量

本文关键字:方法 运行 并行 | 更新日期: 2023-09-27 18:00:58

在我的类中,我有一个下载函数。现在,为了不允许太多的并发下载,我想阻止这个功能,直到"下载点"免费为止;(

void Download(Uri uri)
{
    currentDownloads++;
    if (currentDownloads > MAX_DOWNLOADS)
    {
        //wait here
    }
    DoActualDownload(uri); // blocks long time
    currentDownloads--;
}

在C#/.NET中有现成的编程模式吗?

edit:不幸的是,我不能使用.net4.5中的功能,只能使用.net4.0

限制并行运行方法的数量

可能是这个

var parallelOptions = new ParallelOptions
{        
    MaxDegreeOfParallelism = 3
};
Parallel.ForEach(downloadUri, parallelOptions, (uri, state, index) =>
{
    YourDownLoad(uri);
});

对于这个并发问题,您应该使用Semaphore,请参阅文档中的更多信息:https://msdn.microsoft.com/en-us/library/system.threading.semaphore(v=vs.110(.aspx

对于这种情况,我用一些方法在QueryManager这样的自定义类中创建自己的Queue<MyQuery>

  1. 每个新查询都在Queue<MyQuery>查询中排队
  2. 在每个查询答案中的每个"入队"AND之后,我调用checkIfQueryCouldBeSent()
  3. checkIfQueryCouldBeSent()方法检查您的条件:伴随查询的数量,等等。在您的情况下,如果全局计数器小于5,则接受启动新查询。然后递增计数器
  4. 递减查询答案中的计数器

只有当所有查询都是异步的时,它才有效。您必须将回调存储在MyQuery类中,并在查询结束时调用它。

您正在进行异步IO绑定工作,不需要使用多个线程来调用Parallel.ForEach

您可以简单地使用BCL中公开的自然异步API,即使用HttpClient进行HTTP调用的API。然后,您可以使用SemaphoreSlim和异步等待的WaitAsync方法来限制连接:

private readonly SemaphoreSlim semaphoreSlim = new SemaphoreSlim(3);
public async Task DownloadAsync(Uri uri)
{
    await semaphoreSlim.WaitAsync();
    try
    {
        string result = await DoActualDownloadAsync(uri);
    }
    finally
    {
        semaphoreSlim.Release();
    }
}

您的DoActualyDownloadAsync将使用HttpClient来完成它的工作。大致如下:

public Task<string> DoActualDownloadAsync(Uri uri)
{
    var httpClient = new HttpClient();
    return httpClient.GetStringAsync(uri);
}