【发布时间】:2021-08-29 18:35:27
【问题描述】:
这是我的代码。用于读取文件行的 WPF 按钮的事件处理程序:
private async void Button_OnClick(object sender, RoutedEventArgs e)
{
Button.Content = "Loading...";
var lines = await File.ReadAllLinesAsync(@"D:\temp.txt"); //Why blocking UI Thread???
Button.Content = "Show"; //Reset Button text
}
我在 .NET Core 3.1 WPF App 中使用了异步版本的 File.ReadAllLines() 方法。
但它阻塞了 UI 线程!为什么?
更新:和@Theodor Zoulias一样,我做了一个测试:
private async void Button_OnClick(object sender, RoutedEventArgs e)
{
Button.Content = "Loading...";
TextBox.Text = "";
var stopwatch = Stopwatch.StartNew();
var task = File.ReadAllLinesAsync(@"D:\temp.txt"); //Problem
var duration1 = stopwatch.ElapsedMilliseconds;
var isCompleted = task.IsCompleted;
stopwatch.Restart();
var lines = await task;
var duration2 = stopwatch.ElapsedMilliseconds;
Debug.WriteLine($"Create: {duration1:#,0} msec, Task.IsCompleted: {isCompleted}");
Debug.WriteLine($"Await: {duration2:#,0} msec, Lines: {lines.Length:#,0}");
Button.Content = "Show";
}
结果是:
Create: 652 msec msec, Task.IsCompleted: False | Await: 15 msec, Lines: 480,001
.NET Core 3.1、C# 8、WPF、调试版本 | 7.32 Mb 文件 (.txt) |硬盘 5400 SATA
【问题讨论】:
-
你对正在阅读的文本文件做了什么,它有多大?例如,如果您在读取文件内容后立即将文本添加到文本框,则会在填充文本框时阻塞 UI 线程。
-
调用本身不会阻塞。通话结束后将所有内容注释掉,然后自己查看。
-
我的建议 - 按照答案中的建议使用
var lines = await Task.Run(() => File.ReadAllLines(@"D:\temp.txt"));,它不仅可以保持 UI 响应,而且 7x faster 比ReadAllLinesAsync更好! -
@aepot 您可以尝试稍微改进一下问题,例如修复大小写并正确格式化代码。这将增加该问题被重新投票的可能性(需要再投票一次)。
标签: c# wpf asynchronous async-await .net-core-3.1