我有以下课程:
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时,阻塞消失了。
答案 0 :(得分:1)
您忘记了在读取所有数据后关闭流。试试这个,它会起作用:
using (var stream = client.OpenRead(new Uri(website)))
{
...
}
我不确定 OpenRead 方法是做什么的,但我认为它分配了一些有限的资源,你不能使用超过可用的资源。我个人总是假设如果一个方法返回一个流,那么我必须关闭它。