Skip to main content
 首页 » 编程设计

c#之WebClient.DownloadProgressChanged : Console. WriteLine() 正在阻塞 UI 线程

2024年02月06日25java哥

我有以下简单代码:

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 事件触发得非常快......似乎每秒数百次,这意味着它也在尝试快速写入控制台。

您可以限制写入控制台的频率,这将解决问题(我通过尝试下载 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 + "%)" 
            ); 
    } 
}