我的Caliburn Micro UI因为TDocument中包含的一组相当高级的控件而被锁定。我尝试了几种不同的异步方法将活动转移到另一个线程,但没有成功。这是代码的简化视图。您可能会认出它,因为它来自 Hello Screens 示例应用程序。
要简要了解文档导体的工作原理,请参阅界面:
Public MustInherit Class DocumentWorkspace(Of TDocument As {Class, INotifyPropertyChanged, IDeactivate, IHaveDisplayName})
Inherits Conductor(Of TDocument).Collection.OneActive
Implements IDocumentWorkspace
Protected Sub New()
Public MustOverride ReadOnly Property Icon As String Implements IWorkspace.Icon
Public MustOverride Property IconName As String Implements IWorkspace.IconName
Public Property PixelLabTransitions As BindableCollection(Of Transition)
Public Property ScreenTransition As Transition
Public Property State As DocumentWorkspaceState
Public Property Status As String Implements IWorkspace.Status
Protected ReadOnly Property Conductor As IConductor
Public Overrides Sub ActivateItem(item As TDocument)
Public Sub Edit(child As TDocument)
Public Sub Hide()
Public Sub Show() Implements IWorkspace.Show
End Class
以下是有问题的代码:
_SelectedDesignerElement = value
'adjust Count located next to Icon
vm.DisplayName = value.DesignerDisplayText
count += 1
vm.IsDirty = True
'the next line of code works but
'disables the UI for a long time
Edit(vm)
所以我能说明问题的最简单方法是尝试将这个长活动移到另一个线程:
'Plan to show a Busy indicator here
'Below I have tried to move the edit to another thread
'but this simply does not work
Dim t As Task = Task.Factory.StartNew(Sub()
Edit(vm)
End Sub)
t.Wait()
'Plan to remove Busy indicator here
有没有人更好地了解如何为这个漫长的过程释放用户界面?
BTW问题显然是编辑(VM)在另一个线程上不满意的事实,因为我使用Busy指示器测试相同的方法只使用计数器来创建延迟并且Start Busy / End Busy工作正好很好,UI仍然保持响应。答案 0 :(得分:0)
顿悟发生在我半夜醒来之后。 Hello Screens项目被导入到当前版本的Visual Studio(2015)中,但我从未意识到目标框架将与原始项目保持一致。因此,框架指向了Async和Await支持之前的版本。
我已经完成了向Caliburn.Micro Hello Screens示例项目添加Public Domain Busy Indicator。有几种不同的情况,您可能需要忙碌指示器,并有几种不同的方式来激活控件。例如,我发现在我原来的问题中激活忙碌的地方是:在DocumentWorkspace中,如下所示。
Public Async Sub ShowAsync() Implements HelloScreensWPF.Framework.IWorkspace.ShowAsync
'Notice that this Sub is Async and the Name is changed from Show (In the CM Sample) to Show Async
'Not sure this is the very best way but it works pretty good
'Anytime the user clicks an icon at the bottom of the UI this sub is called
Dim haveActive = TryCast(Parent, IHaveActiveItem)
If haveActive IsNot Nothing AndAlso haveActive.ActiveItem Is Me Then
DisplayName = IconName
State = DocumentWorkspaceState.Master
Else
'We need to have access to the ShellViewModel
Dim Svm = CType(Parent, ShellViewModel)
'Activate the Busy indicator
'The BusyIndicatorViewModel has a built in '200 µ Sec Delay
'So if it is Deactivated before it 'fires' the user will not see a
'flash of an unnecessary Busy Indicator
Svm.ShellBusyIndicator.ShowBusyIndicator(True, True, "Loading", IconName)
'You will need to push the conductor ActivateItem off to another thread for a real application and
'get rid of the Sample Task.Delay here
Await Task.Delay(4000)
Conductor.ActivateItem(Me)
Dim list = CType(Parent, IConductor).GetChildren
'Deactivate Busy Indicator
Svm.ShellBusyIndicator.ShowBusyIndicator(False)
End If
End Sub
如果有人想要使用Busy Solution的HelloScreens副本,只需给我发一封带有@的aqsi.net的电子邮件。