#multithreading #caliburn.micro
#многопоточность #caliburn.micro
Вопрос:
Мой 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
У кого-нибудь есть идея получше, как освободить пользовательский интерфейс для этого затянувшегося процесса?
Кстати, проблема, очевидно, заключается в том, что редактирование (VM) не устраивает в другом потоке, потому что я протестировал тот же подход с индикатором занятости, используя только счетчик для создания задержки, а начальная занятость / конечная занятость работают просто отлично, и пользовательский интерфейс остается отзывчивым.
Ответ №1:
Прозрение произошло после того, как я проснулся посреди ночи. Проект Hello Screens был импортирован в текущую версию Visual Studio (2015), но мне никогда не приходило в голову, что целевая среда останется такой же, как и исходный проект. Таким образом, фреймворк указывал на версию до асинхронной и ожидал поддержки.
Я завершил добавление индикатора занятости в общедоступном домене в Caliburn.Micro Hello отображает пример проекта. Существует несколько различных ситуаций, в которых может возникнуть необходимость в индикаторе занятости, и существует несколько различных способов активации элемента управления. Например, я обнаружил, что место для активации Busy в моем первоначальном вопросе: в 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
Если кому-то нужна копия HelloScreens с решением Busy, просто отправьте мне электронное письмо по адресу aqsi.net с помощью @.