使用async / await与多个任务时UI不更新

时间:2018-01-15 18:45:52

标签: c# user-interface async-await

我正在编写一些示例代码,演示异步/等待演示文稿我给出了由于某种原因标签内容未按预期更新。

    private async void AsyncAwaitButton_Click(object sender, RoutedEventArgs e)
    {
        this.AsyncAwaitButton.IsEnabled = false;
        var start = DateTime.Now;
        IList<Task> tasks = new List<Task>();
        for (int i = 0; i < int.Parse(this.IterationsTextBox.Text); i++)
        {
            tasks.Add(this.ReadTextAsync(this.dataPath));
        }

        await Task.WhenAll(
            tasks.Select(
                async x =>
                    {
                        this.AsyncAwaitData.Content = $"Elapsed time: {DateTime.Now - start}";
                        await x;
                    }));
        this.AsyncAwaitButton.IsEnabled = true;
    }

    private async Task<string> ReadTextAsync(string filePath)
    {
        using (
            var sourceStream = new FileStream(
                filePath,
                FileMode.Open,
                FileAccess.Read,
                FileShare.Read,
                bufferSize: 4096,
                useAsync: true))
        {
            var sb = new StringBuilder();

            var buffer = new byte[0x1000];
            int numRead;
            while ((numRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
            {
                var text = Encoding.UTF8.GetString(buffer, 0, numRead);
                sb.Append(text);
            }

            return sb.ToString();
        }
    }

现在,如果我正确理解自己的代码,Select语句正在创建IEnumerable<Task>,其中每个任务都在等待前面{{1}填充的tasks变量中的相应任务循环。然后将此for传递给IEnumerable<Task>

我希望由于Task.WhenAll产生线程,UI将有足够的机会重新绘制以反映更改的标签内容,但由于某种原因,它只在所有任务完成后才更新。即使添加await x;似乎也不会影响行为。

我错过了什么?

1 个答案:

答案 0 :(得分:-3)

代码在不支持异步文件操作的操作系统上运行,因此FileStream.ReadAsync同步运行,尽管名称中包含Async并返回Task 。由于该方法正在同步运行,所以等待它的所有方法同步运行,这最终成为您已经显示的所有代码。

由于您需要此操作以异步方式运行,为了不阻止UI线程,您别无选择,只能使用Task.Run来呼叫ReadTextAsync(或ReadAsync如果您愿意)确保操作实际异步运行。