我跑这个人代码。它的工作为主,但是当我把它放在我的课是不工作。为什么? 如何使用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();
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top