DownloadDataAsync +委托C#工作在主,但不上课功能
题
我跑这个人代码。它的工作为主,但是当我把它放在我的课是不工作。为什么? 如何使用WebClient.DownloadDataAsync(在这种情况下)的方法?
有崩溃BC数据== null并且抛出异常空:(
。public class Test2
{
public void func()
{
byte[] data = null;
WebClient client = new WebClient();
client.DownloadDataCompleted +=
delegate(object sender, DownloadDataCompletedEventArgs e)
{
data = e.Result;
};
Console.WriteLine("starting...");
client.DownloadDataAsync(new Uri("https://stackoverflow.com/questions/"));
while (client.IsBusy)
{
Console.WriteLine("\twaiting...");
Thread.Sleep(100);
}
Console.WriteLine("done. {0} bytes received;", data.Length);
}
}
//i tried calling on form_load and a button click
new Test2().func();
解决方案
此代码具有竞争条件。该DownloadDataCompleted匿名委托是从不同的线程调用比data.Length调用进行,并在该DownloadDataCompleted被称为IsBusy点变为假。这是谁第一个访问数据两个线程之间的竞争。如果说之前的数据设定下载线程在主线程调用data.Length你得到你的空引用异常。它必须很容易看到,如果你强迫DownloadDataCompleted删除总是通过添加了Thread.Sleep失去了比赛(),它集数据之前调用它。
在线程的状态将是这样的:
Main Thread Download Thread client.IsBusy
Waiting.... downloading... true
leaves waiting loop calls delegate false
calls data.Length data = e.Result
有无法知道哪个线程将首先运行的最后一行的方式。在多处理器机器上,这两个可能的同时运行。
由于这是所有基于定时有时它会工作,有时会失败。您需要某种在由复式线程访问的所有数据同步(锁定)的
其他提示
由于的winform的线程模型(如shf301
指出的),我修改其适用于我的代码。
private void button1_Click(object sender, EventArgs e)
{
func();
}
void func()
{
WebClient client = new WebClient();
byte[] data = null;
long rcv = 0; //last number of bytes received
//check data received for progress
client.DownloadProgressChanged += delegate(object sender, DownloadProgressChangedEventArgs e)
{
if (e.BytesReceived - rcv > 1000)
{
Console.WriteLine("\tBytes Received: " + e.BytesReceived.ToString());
rcv = e.BytesReceived;
}
//else don't report
Thread.Sleep(1);
};
client.DownloadDataCompleted +=
delegate(object sender, DownloadDataCompletedEventArgs e)
{
data = e.Result;
Console.WriteLine("done. {0} bytes received;", data.Length);
};
Console.WriteLine("starting...");
//fire and forget
client.DownloadDataAsync(new Uri("http://stackoverflow.com/questions/"));
}
有是输出:
starting...
Bytes Received: 8192
Bytes Received: 11944
Bytes Received: 15696
Bytes Received: 20136
Bytes Received: 24232
Bytes Received: 28040
Bytes Received: 32424
Bytes Received: 36176
Bytes Received: 40616
Bytes Received: 44712
Bytes Received: 48269
done. 48269 bytes received;
这对我的作品?
C:\TEMP\ConsoleApplication5\bin\Debug>ConsoleApplication5.exe
starting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
done. 48178 bytes received;
什么用,如果你等待结果在一个循环的异步方法的意义呢?只使用同步版本:
public class Test2
{
public void func()
{
WebClient client = new WebClient();
byte[] data = client.DownloadData(new Uri("http://stackoverflow.com/questions/"));
Console.WriteLine("done. {0} bytes received;", data.Length);
}
}
//i tried calling on form_load and a button click
new Test2().func();
不隶属于 StackOverflow