我使用以下代码读取网络驱动器上的所有图像,并在每个图像上弹出ImageControl
,然后在屏幕上显示它们。
我遇到的问题是,无论是PopulateImages()
async
方法,还是运行Task.WaitAll
,用户界面仍会被锁定,直到所有图片都呈现为止。
我是否错误地执行了async/await
?我需要做些什么来解决这个问题?
public MainWindow()
{
InitializeComponent();
Loaded += (s, e) => PopulateImages();
}
private async void PopulateImages()
{
string StartDirectory = @"//path/to/network/folder";
Task.WaitAll(Directory
.EnumerateFiles(StartDirectory)
.Select(filename => Task.Run(async () =>
{
Bitmap resizedImage;
using (var sourceStream = File.Open(filename, FileMode.Open))
{
using (var destinationStream = new MemoryStream())
{
await sourceStream.CopyToAsync(destinationStream);
resizedImage = ResizeImage(new Bitmap(destinationStream), 96, 96);
}
}
Dispatcher.BeginInvoke(new Action(() =>
{
var imgControl = new ImageControl(filename, resizedImage);
stackpanelContainer.Children.Add(imgControl);
}));
})).ToArray());
}
答案 0 :(得分:8)
您正在使用Task.WaitAll
- 阻止,直到完成所有任务。
相反,您应该使用Task.WhenAll
,它会返回Task
,当所有其他任务完成后,它将自动完成。然后你可以等待它。
await Task.WhenAll(...);
虽然说实话,除非你在任务完成后需要做任何事情,否则你根本不需要等待它们。
答案 1 :(得分:0)
不要注册Loaded
事件,而应考虑覆盖FrameworkElement.OnInitialized
方法。这样,如果您的await
不太重,那么您可以在PopulateImage
上Task.WaitAll
保存Task.Run
并可能无需使用ResizeImage
:
public override async void OnInitialized()
{
await PopulateImages();
base.OnInitialized();
}
private async Task PopulateImages()
{
string StartDirectory = @"//path/to/network/folder";
Directory.EnumerateFiles(StartDirectory)
.Select(filename => async () =>
{
Bitmap resizedImage;
using (var sourceStream = File.Open(filename, FileMode.Open))
using (var destinationStream = new MemoryStream())
{
await sourceStream.CopyToAsync(destinationStream);
resizedImage = ResizeImage(new Bitmap(destinationStream), 96, 96);
}
}
var imgControl = new ImageControl(filename, resizedImage);
stackpanelContainer.Children.Add(imgControl);
}