【问题标题】:DownloadRangeToByteArrayAsync in .NET Core 2.0 Multithreading/Async Issues.NET Core 2.0 多线程/异步问题中的 DownloadRangeToByteArrayAsync
【发布时间】:2018-08-25 22:13:29
【问题描述】:

我在 .NET Core 2.0 上的 Microsoft.AzureStorage 9.1 Nuget 包中遇到了 DownloadRangeToByteArrayAsync 方法的问题。每当我以并行或异步方式执行 DownloadRangeToByteArrayAsync 时,都会导致任何后续耗时操作的性能问题。这是我使用的代码:

static void Main(string[] args)
    {
        var storageAccount = CloudStorageAccount.Parse("<access_string>");
        var blobClient = storageAccount.CreateCloudBlobClient();
        var container = blobClient.GetContainerReference("<container_name>");
        List<CloudBlockBlob> listBlobs = new List<CloudBlockBlob>();
        for (int c = 0; c < 100; c++)
        {
            listBlobs.Add(container.GetBlockBlobReference("<file_name>"));
        }

        var tasks = listBlobs.Select(async bl =>
        {
            byte[] buffer = new byte[128];
            await bl.DownloadRangeToByteArrayAsync(buffer, 0, 65536, 128);
            return buffer;
        });
        Task.WaitAll(tasks.ToArray());

        for (int c = 0; c < 100; c++)
        {
            Stopwatch sw = Stopwatch.StartNew();
            byte[] buffer = new byte[1024];
            listBlobs[0].DownloadRangeToByteArrayAsync(buffer, 0, 65536 * c, 1024).Wait();
            Console.WriteLine(sw.ElapsedMilliseconds);
        }
        Console.Read();
    }
}

当我执行上述代码时,在 Task.WaitAll() 之后,以下循环的每次迭代都需要很长时间。与我的代码中没有包含 Task.WaitAll 相比,每次迭代花费的时间是 4 倍以上。与在 .NET Framework 4.6.1(也使用 WindowsAzure.Storage 9.1.0)中执行完全相同的代码所花费的时间也增加了 4 倍。用 Parallel.ForEach 替换 Select 语句也会导致同样的问题,但如果我在 DownloadRangeToByteArrayAsync 上使用 .Wait() 而不是 await 就可以了。同样经过大约 2 分钟的 LINQ/Parallel 语句,所有后续操作的运行时间都恢复正常。此外,当我调试它时,它显示 LINQ 语句(或 Parallel.ForEach)在 .NET Core 上创建了 100 多个线程,而在 .NET Framework 上只创建了大约 10 个。此外,这 100 多个线程中的大多数都没有消失,即使在一个多小时后也是如此。

有谁知道导致问题的 DownloadRangeToByteArrayAsync 或线程从 .NET Framework 4.6.1 更改为 .NET Core 2.0 是怎么回事?

【问题讨论】:

    标签: c# multithreading async-await .net-core azure-blob-storage


    【解决方案1】:

    我在并发异步活动目录调用时也遇到过这种情况。我认为危险信号是 .Net Core 生成了如此多的并行线程,100 对 10。为了解决我的问题,我限制了允许的并行量。

    Parallel.ForEach(
        listBlobs,
        new ParallelOptions { MaxDegreeOfParallelism = 10 },
        listBlob => { 
            // Do stuff
        }
    );
    

    【讨论】:

    • 尝试使用较小的数字,它确实降低了线程数,但仍然创建了一些垃圾线程,即使将 MaxDegreeofParallelism 增加到 3 也会导致一些相当严重的性能问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-26
    • 2018-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多