2016-11-21 75 views
-1

假设一个场景,其中我有主UI线程上运行的实例方法,添加自定义UserControl(WPF)到可经由单访问的主应用程序窗口,然后需要进一步执行等待,直到用户与UserControl互动,并返回一些值。如何在主UI线程中等待用户交互而不阻塞它?

我的第一次尝试总是会阻塞UI线程,因此用户实际上无法与UserControl进行交互,直到我最终遇到了asyncawait

以下是我想出了解决方案的简化要点:

Public Class ControlManagerA 
    Inherits ControlManagerBase 

    Public Property userControlResult As String 

    Public Overrides Async Function CreateAndWait() As Task 

     'Initialize to some default value to indicate that no response was received yet. 
     userControlResult = Nothing 

     Dim myCustomControl As New MyCustomUserControlA() 
     'Could also pass any additional parameters required for display. 
     myCustomControl.AssignParent(Me) 

     GlobalUIManager.GetMainWindow().AssignUserControl(myCustomControl) 

     'This will eventually be populated with a proper value due to 
     'user interaction in MyCustomUserControlA. 
     While userControlResult Is Nothing 
      'This is the part that I am a little unhappy about. 
      Await Task.Delay(1) 
     End While 

     GlobalUIManager.GetMainWindow().RemoveUserControl(myCustomControl) 

     DoSomethingWithResult(userControlResult) 

    End Function 
End Class 

一件事情困扰我的是,我忙着等待一个循环那里。 (而事实上,我大概也通过userControlResultByRef参数,而不是等待MyCustomUserControlA通过公共属性来访问它。) 的解决方案仍在研究,我和我完全不注意到任何性能问题,但我想知道是否有更好的方法来等待这里的结果。我也不知道,如果Task.Delay(1)是一种浪费,或者如果它实际上是在开销方面相当轻巧。

+0

似乎是从'ControlManagerA'(或其他一些回调机制)处理的'MyCustomUserControlA'引发一个事件会减少耦合并简化一些事情,但也许我不理解整个图像? – Mark

+0

代码流需要在特定方法中继续,这就是为什么我需要在那里等待。我不能在稍后的时间继续进行一个事件,这会启动一个单独的流程(至少不是没有等待该事件)。 –

回答

1

虽然你可以await UI things such as button clicks,这样做是有问题的。如果用户做了其他事情,如关闭该窗口怎么办?或者点击其他地方?

这是更好地设计出不会将用户限制到一个单一的UI工作流程UX。

+0

该应用程序是一款游戏,因此没有实际的“工作流程指南”可供遵循。对于玩家来说,实际上会有一个麻烦,那就是有多个窗口出现并且不存在(这是我过去的 - 这实际上是试图摆脱这种设计)。如果该用户控件进场时,唯一的可点击的东西实际上是在用户控件的东西,虽然UI的其他部分仍可能可见。 关闭该窗口意味着离开游戏。 (是的,我知道WPF可能不是.NET中最适合的游戏,但是我滥用它:)) –

+0

然后,你的链接让我意识到了'TaskCompletionSource',这似乎是做我需要的。我会试着去看看它是否适用于我的情况。 –