这是我的方法
private async void OpenDetailWindow()
{
using (DetailView detailView = new DetailView ())
{
DialogResult result = new DialogResult();
mainView.BeginInvoke(new Action(() =>
{
result = detailView.ShowDialog();
}));
Bitmap img = null;
if (!detailView.IsHandleCreated) detailView.CreateControl();
await Task.Run(new Action(() =>
{
img = GetAnImage();
if (!detailView.IsDisposed && result == DialogResult.None)
{
detailView.BeginInvoke(new Action(() =>
{
detailView.Image = img;
}));
}
}));
while (result == DialogResult.None)
{
await Task.Delay(10);
}
if (result == DialogResult.OK)
{
UpdateRecord()
detailView.Close();
detailView.Dispose();
if (img != null) img.Dispose();
}
else (result == DialogResult.Cancel)
{
detailView.Close();
detailView.Dispose();
if (img != null) img.Dispose();
}
}
}
为了简要说明发生了什么,我正在显示一个显示图像的新表单,但图像可能需要几秒钟才能下载,因此在下载图像时首先显示表单。我在一些地方简化了它并删除了一些东西
因为这不是同步的,所以我不得不等待表格被关闭的一些迹象。是的,我需要使用ShowDialog
因为我想要那种行为
while (result == DialogResult.None)
{
await Task.Delay(10);
}
整个while循环等待结果似乎是错误的,但我找不到更干净的方法。我应该使用事件,还是......?
答案 0 :(得分:3)
如果您利用await
返回UI线程的方式,这种事情会容易得多。因此,不是让不同的线程“发送彼此更新”等等,而是让UI线程控制所有内容。
在你的情况下,我将一些异步初始化移到DetailView
类中,使用我的article on asynchronous data binding中的一些想法(用MVVM编写,但基本概念适用于任何UI):
public class DetailView
{
public DetailView()
{
// Synchronously load palceholder image.
Image = <placeholder>;
// Asynchronously load real image.
LoadImageAsync();
}
private async Task LoadImageAsync()
{
try
{
Image = await Task.Run(() => GetAnImage());
}
catch (Exception ex)
{
// TODO: Determine what to do if the image loading fails.
}
}
public Bitmap Image { get; private set; }
Dispose() { Image?.Dispose(); }
}
然后您可以这样使用此类型(假设在UI线程上调用OpenDetailWindow
):
private async OpenDetailWindow()
{
using (DetailView detailView = new DetailView())
{
var result = detailView.ShowDialog();
if (result == DialogResult.OK)
UpdateRecord()
}
}