c# - SemaphoreSlim 适用于 foreach,但不适用于
问题描述
我对使用信号量有点陌生,对此我有点困惑。我所做的只是从页面中获取 html 代码,然后一遍又一遍地将其写入文件。当我在 foreach 中使用它时,它工作得很好。当我将其更改为 for 循环时,我得到一个文件被另一个进程异常使用,它引用了最大计数之后的文件。这两者有什么区别?他们应该处理相同的文件。
完美运行:
private async Task GetFiles()
{
string strDir = ConfigurationManager.AppSettings["location"];
var maxThreads = 4;
var allTasks = new List<Task>();
SemaphoreSlim throttler = new SemaphoreSlim(initialCount: maxThreads);
foreach(FileToProcess ftpFile in lstFiles)
{
await throttler.WaitAsync();
allTasks.Add(
Task.Run(async () =>
{
try
{
await GetHtmlFromUrlAsync(ftpFile, strDir);
}
finally
{
throttler.Release();
}
}));
}
await Task.WhenAll(allTasks);
}
在列表中的第 5 项(最大线程 + 1)之后获取错误。如果我调整了最大线程数,错误也会改变:
private async Task GetFiles()
{
string strDir = ConfigurationManager.AppSettings["location"];
var maxThreads = 4;
var allTasks = new List<Task>();
SemaphoreSlim throttler = new SemaphoreSlim(initialCount: maxThreads);
for (int x = 0; x < lstFiles.Count; x++)
{
await throttler.WaitAsync();
allTasks.Add(
Task.Run(async () =>
{
try
{
await GetHtmlFromUrlAsync(lstFiles[x], strDir);
}
finally
{
throttler.Release();
}
}));
}
await Task.WhenAll(allTasks);
}
解决方案
推荐阅读
- node.js - 如何使用 Node.js 子进程在后台运行命令提示符?
- visual-studio-code - Visual Studio 区域折叠相同格式的 phpstorm
- php - PHP array_map() 和 mysqli_real_escape_string()
- java - 如何找到使用背包切割库存问题的最佳组合
- firebase - 如何从 Rest API 向用户段发送数据消息
- .net - 有没有办法检查活动窗口是否打开了 IntelliSense 弹出窗口?
- php - 我想使用键值对 PHP 数组进行分组
- hyperloglog - 基于 HyperLogLog 的使用分析是否符合 GDPR?
- node.js - 如何使用浏览器网络内存中显示的API返回的错误?
- rename - 使用条件语句重命名文件