在我班上我有一个下载功能。现在为了不允许过多的并发下载,我想阻止这个功能,直到" download-spot"是免费的;)
void Download(Uri uri)
{
currentDownloads++;
if (currentDownloads > MAX_DOWNLOADS)
{
//wait here
}
DoActualDownload(uri); // blocks long time
currentDownloads--;
}
在C#/ .NET中是否有现成的编程模式?
编辑:遗憾的是,我无法使用.net4.5中的功能,只能使用.net4.0
答案 0 :(得分:3)
可能是这个
var parallelOptions = new ParallelOptions
{
MaxDegreeOfParallelism = 3
};
Parallel.ForEach(downloadUri, parallelOptions, (uri, state, index) =>
{
YourDownLoad(uri);
});
答案 1 :(得分:2)
您应该使用信号量来解决此并发问题,请参阅文档中的更多内容: https://msdn.microsoft.com/en-us/library/system.threading.semaphore(v=vs.110).aspx
答案 2 :(得分:1)
对于这种情况,我在自定义类Queue<MyQuery>
中创建了自己的QueryManager
,并使用了一些方法:
Queue<MyQuery>
个查询checkIfQueryCouldBeSent()
checkIfQueryCouldBeSent()
方法检查您的条件:伴随查询的数量,依此类推。在您的情况下,如果全局计数器小于5,则接受启动新查询。并且递增计数器仅当所有查询都是异步时才有效。
您必须在MyQuery
类中存储Callback,并在查询结束时调用它。
答案 3 :(得分:1)
您正在执行异步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);
}