class Program
{
private void DownloadFile(WebClient wc,string path)
{
Uri address = new Uri(path);
wc.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadFinished);
wc.DownloadFileAsync(address, "D:/123.png");
}
private void DownloadFinished(object sender, AsyncCompletedEventArgs e)
{
Console.WriteLine(e.Error.Message);
Console.WriteLine(e.Error.GetBaseException());
}
static void Main(string[] args)
{
WebClient wc = new WebClient();
new Program().DownloadFile(new WebClient(), "https://online.visual-paradigm.com/images/features/uml-tool/03-use-case-diagram-example-atm.png");
Console.WriteLine("Finish Download");
Console.Read();
}
}
網路上下載的範例拿來下載圖片,但發現運行會報錯
請問為甚麼會報錯?
下面這段程式碼出錯,錯誤訊息是,並未將物件參考設定為物件的執行個體
Console.WriteLine(e.Error.Message);
Debug 看一下可以發現 e.Error 等於 null,
接著去看了一下 AsyncCompletedEventArgs 的程式碼說明,
Error 這個屬性,只有在下載失敗時才有值,成功時會等於 null,
所以這段程式碼下載的部分應該是正確的,大大可以去資料夾看看,
圖片應該有下載成功。
然後還有個小問題,下面這段程式碼,會在圖片下載完成前執行,
但正常的邏輯應該要圖片真正下載完,才印出 Finish Download
。
Console.WriteLine("Finish Download");
所以可以這麼修改,在 DownloadFinished 裡面判斷如果下載失敗,e.Error != null
印出錯誤訊息,否則就代表下載成功,
印出 Finish Download ,程式碼如下:
private void DownloadFinished(object sender, AsyncCompletedEventArgs e)
{
if (e.Error != null)
{
Console.WriteLine(e.Error.Message);
Console.WriteLine(e.Error.GetBaseException());
}
else
{
Console.WriteLine("Finish Download");
}
}
測試是還沒等到異步下載圖片的程序走完,
程式就運行結束了,才報出Exception
改成等待Task完成後才關閉程式版本,就可以。
以下範例:
class Program
{
static Task task;
private void DownloadFile(WebClient wc,string path)
{
Uri address = new Uri(path);
task = wc.DownloadFileTaskAsync(address, $@"D:/{Guid.NewGuid()}.png"); //把Task保存下來
}
private void DownloadFinished(object sender, AsyncCompletedEventArgs e)
{
Console.WriteLine(e.Error.Message);
Console.WriteLine(e.Error.GetBaseException());
}
static void Main(string[] args)
{
WebClient wc = new WebClient();
new Program().DownloadFile(new WebClient(), "https://online.visual-paradigm.com/images/features/uml-tool/03-use-case-diagram-example-atm.png");
task.Wait(); //等待Task完成
Console.WriteLine("Finish Download");
Console.Read();
}
}