繁体   English   中英

Task.WaitAll无限期阻止

[英]Task.WaitAll is blocking indefinitely

我有以下课程:

class MultiWebProgram
{
  static void Main(string[] args)
  {
    string[] websites = new string[]
    {
       "https://www.google.com/search?q=one",
       "https://www.google.com/search?q=two",
       "https://www.google.com/search?q=three",
       "https://www.google.com/search?q=four"
    };

    Task<int>[] taskList = new Task<int>[websites.Length];
    int i = 0;
    foreach(var website in websites)
    {
      taskList[i] = Task<int>.Run(() => GetSiteBytes(website));
      i++;
    }
    Task.WaitAll(taskList);
  }

  public static int GetSiteBytes(string website)
  {
    WebClient client = new WebClient();
    var stream = client.OpenRead(new Uri(website));
    byte[] buffer = new byte[4096];
    int totalBytes = 0;
    int bytesRead = 0;
    do
    {
      bytesRead = stream.Read(buffer, 0, 4096);
      totalBytes += bytesRead;
    }
    while (bytesRead >= 4096);
    Console.WriteLine("Got {0} bytes from {1}", totalBytes, website);
    return totalBytes;
  }
}

当我运行此代码时,代码将在WaitAll命令上阻塞。

我尝试将程序更改为此:

class MultiWebProgram
{
  static void Main(string[] args)
  {
    string[] websites = new string[]
    {
       "https://www.google.com/search?q=one",
       "https://www.google.com/search?q=two",
       "https://www.google.com/search?q=three",
       "https://www.google.com/search?q=four"
    };

    Task<int>[] taskList = new Task<int>[websites.Length];
    int i = 0;
    foreach(var website in websites)
    {
      taskList[i] = GetSiteBytesAsync(website);
      i++;
    }
    Task.WaitAll(taskList);
  }

  public async static Task<int> GetSiteBytesAsync(string website)
  {
    WebClient client = new WebClient();
    var stream = await client.OpenReadTaskAsync(new Uri(website));
    byte[] buffer = new byte[4096];
    int totalBytes = 0;
    int bytesRead = 0;
    do
    {
      bytesRead = await stream.ReadAsync(buffer, 0, 4096);
      totalBytes += bytesRead;
    }
    while (bytesRead >= 4096);

    Console.WriteLine("Got {0} bytes from {1}", totalBytes, website);
    return totalBytes;
  }
}

换句话说,我使GetSiteBytes方法异步-但这没什么区别。

我注意到的一件事; 当我启动Fiddler并运行该程序的任何一个版本时,都没有阻塞。

这可能是怎么回事?

**编辑:**问题似乎是OpenRead方法。 当我使用DownloadData / DownloadDataAsync时,阻塞消失了。

您在读取所有数据后忘记关闭流。 试试这个,它将起作用:

using (var stream = client.OpenRead(new Uri(website)))
{
...
}

我不确定OpenRead方法的作用是什么,但我认为它会分配一些有限的资源,并且您不能使用超出可用范围的资源。 我个人始终认为,如果方法返回流,那么我必须将其关闭。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM