如何最好等待DialogResult(异步)

时间:2017-07-31 08:52:03

标签: c# winforms

这是我的方法

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循环等待结果似乎是错误的,但我找不到更干净的方法。我应该使用事件,还是......?

1 个答案:

答案 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()
  }
}