WebClient.DownloadProgressChanged:Console.WriteLine()是阻塞UI线程
我有以下简单的代码:WebClient.DownloadProgressChanged:Console.WriteLine()是阻塞UI线程
private void btn_download_Click(object sender, EventArgs e){
WebClient client = new WebClient();
client.DownloadProgressChanged += client_DownloadProgressChanged;
client.DownloadFileAsync(new Uri("http://.../file.zip"), "file.zip");
}
void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e){
//Prints: "Downloaded 3mb of 61.46mb (4%)"
Console.WriteLine("Downloaded "
+ ((e.BytesReceived/1024f)/1024f).ToString("#0.##") + "mb"
+ " of "
+ ((e.TotalBytesToReceive/1024f)/1024f).ToString("#0.##") + "mb"
+ " (" + e.ProgressPercentage + "%)"
);
}
这是为什么呢阻塞UI线程?当我用代码替换Console.WriteLine()
来更新我的进度条(不在代码中显示)时,它可以工作。用户界面很敏感。
你这样做的方式似乎是MSDN shows in its examples。我也试过了,得到了同样的结果。在单独的线程中运行某些内容时,您会看到类似的行为,然后这些线程会过快地回调主UI线程,并通过更新来加重它。 UI线程得到备份并有效冻结。
DownloadProgressChanged
DownloadProgressChanged
事件触发得很快......似乎是每秒数百次,这意味着它试图快速写入控制台。
你可以限制你多久写到控制台,这将解决这个问题(我测试了它,试图下载一个4GB的ISO,并同时使UI响应写信给控制台):
// define a class-level field variable
private int counter;
private void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
counter++;
// Only print to the console once every 500 times the event fires,
// which was about once per second when I tested it
if (counter % 500 == 0)
{
//Prints: "Downloaded 3mb of 61.46mb (4%)"
Console.WriteLine("Downloaded "
+ ((e.BytesReceived/1024f)/1024f).ToString("#0.##") + "mb"
+ " of "
+ ((e.TotalBytesToReceive/1024f)/1024f).ToString("#0.##") + "mb"
+ " (" + e.ProgressPercentage + "%)"
);
}
}
Perfect dude!这真是令人困惑我。 – Krimson 2014-12-03 02:40:42
我可以ee为什么,因为这正是他们似乎建议在文档中做的事情!包括关于它多久发生一次火灾的说明并不会伤害他们,但我想他们无法预测所有事情。 – 2014-12-03 02:41:57
是否有控制台可以写入?你为什么要从GUI程序写入控制台?在这里使用'Debug'类还是'TraceListener'会更有意义? – 2014-12-03 00:54:42
当文件完全下载时,是否至少更新一次? – 2014-12-03 00:57:54
@PeterDuniho写好控制台基本上输出到“标准输出”,这可以在Visual Studio中的“输出:窗口中查看。添加是的,这会更有意义,但我的问题不是要求替代品。知道背后的原因 – Krimson 2014-12-03 00:57:57