在单独的线程上创建Control然后添加到WPF中的itemssource

时间:2013-10-18 20:32:44

标签: wpf vb.net multithreading ui-thread

我正在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线程?

1 个答案:

答案 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