我正在WPF中的一个单独的STA线程上创建一个控件,并希望将它添加到列表中,然后使用list as as和itemssource作为itemscontrol。
我的代码运行正常,直到我尝试显示控件。我得到一个错误,说不同的线程拥有该列表。
我完全理解为什么会这样,但是我想知道如何将其重新用于UI线程。
我的经常性代码:
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
那么如何才能将List(Of StudioImage)重新放回UI线程?
答案 0 :(得分:1)
我正在WPF中的一个单独的STA线程上创建一个控件,并希望将它添加到列表中,然后使用list as as和itemssource作为itemscontrol。
你不能这样做。基本目标是有缺陷的。
问题是你需要创建WPF在主UI线程上使用的所有控件。在WPF中,FrameworkElements都具有线程关联性 - 它们需要在同一个线程上创建和使用。
在您的情况下,您正在执行的“工作”需要在UI线程上进行。将此推送到后台线程永远不会正常工作,即使你要正确同步(你的代码不是线程安全的,除了现在的WPF方面)。
你应该完全在UI线程上运行你的代码,除非有可能拉出一些与UI不相关的少量工作(从你所展示的内容来看,情况并非如此)。
编辑:
在您的情况下,如果您Freeze()
ImageSource
,则可以在后台构建图片,但不能将其绑定到用户界面。
以下内容应该干净利落地处理,而不会阻止用于解析图像信息的UI。
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