【发布时间】:2017-11-03 11:33:33
【问题描述】:
开发环境:
C#、Visual Studio 2010 (.net 4.0)、win7 x64
winform项目中的代码:
private void Form1_Load(object sender, EventArgs e)
{
string path = "c:\\1.jpg";
for (int i = 0; i < 10; i++)
{
string url = "http://...." + i.ToString() + ".jpg";//i'm sure the http file does exist
using (WebClient wc = new WebClient())
{
wc.DownloadFileCompleted += new AsyncCompletedEventHandler(wc_DownloadFileCompleted);
wc.DownloadFileAsync(new Uri(url), path);
Thread.Sleep(3000);//i'm sure the download will be finished in 3s
WriteLog("C:\\1.log", "main function\r\n");
}
}
}
static void wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
WriteLog("C:\\1.log", "callback function\r\n");
}
static void WriteLog(string LogName, string log)
{
StreamWriter sw = new StreamWriter(LogName, true);
if (sw == null)
return;
sw.Write(System.DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + " " + log);
sw.Close();
}
那么日志将是:
2017/11/03 19:04:48 主要功能
2017/11/03 19:04:51 主要功能
2017/11/03 19:04:54 主要功能
2017/11/03 19:04:57 主要功能
2017/11/03 19:05:00 主要功能
2017/11/03 19:05:03 主要功能
2017/11/03 19:05:06 主要功能
2017/11/03 19:05:09 主要功能
2017/11/03 19:05:12 主要功能
2017/11/03 19:05:15 主要功能
2017/11/03 19:05:15 回调函数
2017/11/03 19:05:15 回调函数
2017/11/03 19:05:15 回调函数
2017/11/03 19:05:15 回调函数
2017/11/03 19:05:15 回调函数
2017/11/03 19:05:15 回调函数
2017/11/03 19:05:15 回调函数
2017/11/03 19:05:15 回调函数
2017/11/03 19:05:15 回调函数
2017/11/03 19:05:15 回调函数
如果 ConsoleApplication 中的代码相同:
static void Main(string[] args)
{
string path = "c:\\1.jpg";
for (int i = 0; i < 10; i++)
{
string url = "http://...." + i.ToString() + ".jpg";//i'm sure the http file does exist
using (WebClient wc= new WebClient())
{
wc.DownloadFileCompleted += new AsyncCompletedEventHandler(wc_DownloadFileCompleted);
wc.DownloadFileAsync(new Uri(url), path);
Thread.Sleep(3000);//i'm sure the download will be finished in 3s
WriteLog("C:\\1.log", "main function\r\n");
}
}
}
static void wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
WriteLog("C:\\1.log", "callback function\r\n");
}
static void WriteLog(string LogName, string log)
{
StreamWriter sw = new StreamWriter(LogName, true);
if (sw == null)
return;
sw.Write(System.DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + " " + log);
sw.Close();
}
那么日志将是:
2017/11/03 19:13:50 回调函数
2017/11/03 19:13:52 主要功能
2017/11/03 19:13:53 回调函数
2017/11/03 19:13:55 主要功能
2017/11/03 19:13:56 回调函数
2017/11/03 19:13:58 主要功能
2017/11/03 19:13:59 回调函数
2017/11/03 19:14:01 主要功能
2017/11/03 19:14:02 回调函数
2017/11/03 19:14:04 主要功能
2017/11/03 19:14:05 回调函数
2017/11/03 19:14:08 主要功能
2017/11/03 19:14:08 回调函数
2017/11/03 19:14:11 主要功能
2017/11/03 19:14:11 回调函数
2017/11/03 19:14:14 主要功能
2017/11/03 19:14:14 回调函数
2017/11/03 19:14:17 主要功能
2017/11/03 19:14:17 回调函数
2017/11/03 19:14:20 主要功能
显然,第二个结果是对的。
但是在第一个项目中,为什么在所有下载完成之前不调用 DownloadFileCompleted 事件?
如何在每次下载完成后立即调用 DownloadFileCompleted 事件?
【问题讨论】:
-
其实两个都对:)
-
似乎 DownloadFileCompleted 回调被第一个项目中的某些东西阻止了,结果不是我想要的。 winform项目中如何得到第二个结果?
-
@JQY 为什么你的
wc_DownloadFileCompleted处理程序在winform项目中是静态的? -
DownloadFileCompleted 事件将努力使您的事件处理程序线程安全。所以你可以在那个事件处理程序中做一些不会让你的程序崩溃的事情,比如更新控件。它可以在 Winforms 应用程序中执行此操作,这要归功于非空 SynchronizationContext.Current,它无法在控制台模式应用程序中执行此操作。结果是,只要你让 UI 线程在 Thread.Sleep() 调用和 for 循环中变得紧张,什么都不会发生。在您的 Load 事件处理程序完成之前,现在这些事件会迅速触发。功能,而不是错误。永远不要挂起 UI 线程。
-
@Hans Passant 感谢您详细的回复,对我找出问题所在非常有帮助。
标签: c# winforms webclient downloadfileasync