首页 > 解决方案 > 当 WebClient 给出超时异常时,使用 TPL (Task.WhenAll) 从 URL 批量读取图像会陷入死锁

问题描述

我创建了一个 .net core 2.0 控制台应用程序,我在其中从 URL 读取图像数据并对其进行处理。由于图像是散装的,我正在做线程。一切正常,但是当图像不返回任何数据并引发超时异常时,线程会卡住/挂起并继续。似乎有些僵局,但我不知道具体在哪里。

下面是我的代码。

int batchSize = 25;
int numberOfBatches = xmlProperties.Count() < batchSize ? 1 : ((((xmlProperties.Count() / batchSize) % 1) == 0) ? (xmlProperties.Count() / batchSize)
                                                                    : (xmlProperties.Count() / batchSize) + 1);
for (int i = 0; i < numberOfBatches; i++)
{
    Task[] Requests = xmlProperties
                        .Skip(i * batchSize)
                        .Take(batchSize)
                        .Select(l => UploadImage(l.PropertyRefNo, l.Images))
                        .ToArray();
    await Task.WhenAll(Requests); // does not return when UploadImage throws exception in WebClient request.
}

public async Task UploadImage(string PropertyRefNo, List<string> Images)
{
    Images = Images.OrderBy(x => x).Take(10).ToList();          

    var index1 = 0;
    foreach (var item in Images)
    {
        try
        {
            index1 = index1 + 1;
            using (MemoryStream imageStream = await ImageUtilities.GetImageData(item)) // Exception comes here in reading data from URL
            {
                // Do Rest Work
            }
        }
        catch (Exception ex)
        {
            await AddLog(0, JobStatus.ImageFailedFull.ToString(), ex.ToString(), PropertyRefNo + " : " + item, 0);
        }
    }
}

public static async Task<MemoryStream> GetImageData(string filename)
{
    try
    {
        using (HttpClient client = new HttpClient())
        {
            var data = await client.GetAsync(filename);
            byte[] imageStream = await data.Content.ReadAsByteArrayAsync();
            return new MemoryStream(imageStream);
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

public class WebClientWithTimeout : WebClient
{
    protected override WebRequest GetWebRequest(Uri address)
    {
        WebRequest wr = base.GetWebRequest(address);
        wr.Timeout = 100000; // 100 seconds
        return wr;
    }
}

任何帮助将不胜感激。

标签: c#.netimage-processingasp.net-core-2.0

解决方案


推荐阅读