Reputation: 385
I am creating a control on a separate STA thread in WPF and want to add it to a list then use the list as and itemssource for an itemscontrol.
My code runs fine until I try to show the control. I get an error saying that a different thread owns the list.
I fully understand why this is, but would like to know how I can get this back on to the UI thread.
My recurring Code:
For Each S In qry
Dim T As New System.Threading.Thread(AddressOf Loader)
T.SetApartmentState(System.Threading.ApartmentState.STA)
T.Start({S, AllBackgrounds})
Next
My Loader Sub:
Private Shared Sub Loader(O As Object)
Dim ISC As New ImageSourceConverter
Dim SI As New StudioImage
SI.Source = ISC.ConvertFromString(O(0))
CType(O(1), List(Of StudioImage)).Add(SI)
End Sub
So how can I get the List(Of StudioImage) back on to the UI thread?
Upvotes: 1
Views: 1071
Reputation: 564403
I am creating a control on a separate STA thread in WPF and want to add it to a list then use the list as and itemssource for an itemscontrol.
You can't do this. The basic goal is flawed.
The problem is that you need to create all of the controls which will be used by WPF on the main UI thread. In WPF, FrameworkElements all have thread affinity - they need to be created and used on the same thread.
In your case, the "work" you are doing all needs to happen on the UI thread. Pushing this into background threads is never going to work properly, even if you were to properly synchronize (your code isn't thread safe, apart from the WPF side of things now).
You should just run your code entirely on the UI thread, unless there is the potential of pulling some small amount of work out that's not UI related (from what you're showing, this isn't the case).
Edit:
In your case, if you Freeze()
your ImageSource
, you can build the images in the background, but you can't bind them to the UI.
The following should handle this cleanly, without blocking the UI for parsing the image information.
For Each si In qry
Dim s as String = si
Dim t = Task.Factory.StartNew(Function()
Dim ISC As New ImageSourceConverter
Dim is = ISC.ConvertFromString(s)
is.Freeze()
Return is
End Function)
t.ContinueWith(Function(a)
Dim SI as New StudioImage
SI.Source = a.Result
AllBackgrounds.Add(SI)
End Function, TaskScheduler.FromCurrentSynchronizationContext())
Next
Upvotes: 1