1

我正在 WPF 中的一个单独的 STA 线程上创建一个控件,并希望将其添加到列表中,然后将该列表用作项目控件和 itemssource。

在我尝试显示控件之前,我的代码运行良好。我收到一条错误消息,指出另一个线程拥有该列表。

我完全理解为什么会这样,但想知道如何才能将其返回到 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

我的装载机子:

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 线程呢?

4

1 回答 1

1

我正在 WPF 中的一个单独的 STA 线程上创建一个控件,并希望将其添加到列表中,然后将该列表用作项目控件和 itemssource。

你不能这样做。基本目标是有缺陷的。

问题是您需要在主 UI 线程上创建 WPF 将使用的所有控件。在 WPF 中,FrameworkElements 都具有线程关联性——它们需要在同一个线程上创建和使用。

在您的情况下,您所做的所有“工作”都需要在 UI 线程上进行。将其推送到后台线程永远不会正常工作,即使您要正确同步(您的代码不是线程安全的,除了现在的 WPF 方面)。

您应该完全在 UI 线程上运行您的代码,除非有可能提取一些与 UI 无关的少量工作(从您所展示的内容来看,情况并非如此)。


编辑:

在您的情况下,如果您Freeze()ImageSource,则可以在后台构建图像,但不能将它们绑定到 UI。

下面应该干净地处理这个问题,而不会阻塞用于解析图像信息的 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
于 2013-10-18T20:39:13.853 回答