2017-07-31 80 views
-1

这里是我的方法如何最好等待的DialogResult(异步)

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循环来等待结果似乎是错误的,但我不能找到这样做的一个更清洁的方式。我应该使用事件,还是...?

回答

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(); } 
} 

然后你就可以使用这种类型的这样(假设OpenDetailWindow被称为UI线程):

private async OpenDetailWindow() 
{ 
    using (DetailView detailView = new DetailView()) 
    { 
    var result = detailView.ShowDialog(); 
    if (result == DialogResult.OK) 
     UpdateRecord() 
    } 
} 
+0

如果我不想在视图中的业务逻辑? – p3tch

+0

@ p3tch:然后将'GetAnImage'移动到一个传递给viewmodel构造函数的服务对象中。 –