[英]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.