首页 > 解决方案 > 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);
    }

标签: c#iosemaphore

解决方案


推荐阅读