views:

275

answers:

1

I have the following problem: Multithreaded WPF application, Model View Presenter Implementation. Presenters and Views that belong together are created by a factory on a separate thread and should get a separate Dispatcher.

Public Function CreatePresenter(Of T As {New, Class})(ByVal p_eCreationOptions As eViewCreationOptions) As T Implements IPresenterFactory.CreatePresenter

    Select Case p_eCreationOptions
        Case eViewCreationOptions.CreateInCallingThread
            CreatePresenter(Of T)()
        Case eViewCreationOptions.CreateInNewThread
            Dim oThread As New Thread(New ThreadStart(AddressOf CreatePresenter(Of T)))
            oThread.SetApartmentState(System.Threading.ApartmentState.STA)
            oThread.Start()
            oThread.Join()
        Case Else
            Throw New InvalidOperationException("Need to specify creation options.")
    End Select

    Return CType(m_oCreatedPresenter, T)

End Function

Private Sub CreatePresenter(Of T As {New, Class})()
    m_oCreatedPresenter = Activator.CreateInstance(Of T)()
End Sub

The problem is, now the presenter is created on the other thread and the thread goes dormant after creation, but the dispatcher on there isn't running yet. Now, if I'm coming from the main UI thread where the application lives and make a call to my presenter, Im creating the view, show it and now only i can call Dispatcher.Run().

Public Overloads Sub Show()
    Console.WriteLine ("Show Caller ThreadID = " & Thread.CurrentThread.ManagedThreadId)
    MyBase.Show()
    System.Windows.Threading.Dispatcher.Run()
End Sub

But what I want to do is, when a method on the presenter is called from another thread than where the presenter lives, invoke the method again on the thread of the presenter where he has his own Dispatcher, so that I don't need to deal with the Dispatcher on calls between my Presenter and the view. Is that possible at all, is my design flawed or is there any better way to achieve what i want?

A: 

The problem is that the Dispatcher doesn't start when there's no DispatcherObject instantiated on the new thread, but if you instantiate a dummy object and then invoke the method of your presenter, the dispatcher will run properly. For example

 private void ThreadStartingPoint()  
 {  
     var dummyDispatcherObject = new Style();  
     Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(CreatePresenterInternal));  
     Dispatcher.Run();  
}

A full solution to this can be found on my blog.

Philipp Braun