2013-10-18 16 views
1

我正在WPF中的单独STA线程上创建控件,并且想要将它添加到列表中,然后使用list和itemssource作为项目控件。在单独的线程上创建控件,然后添加到WPF中的项目源

我的代码运行良好,直到我尝试显示控件。我收到一个错误,说一个不同的线程拥有这个列表。

我完全理解这是为什么,但想知道如何让它回到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 

那么,怎样才能我得到的名单(共StudioImage)回到该UI线程?

+0

你不能这样做。不要在WPF的程序代码中创建或操作UI元素。这就是XAML的用途。如果你想显示图像,确保你在Freezable上调用'.Freeze()',如果它是在后台线程上创建的。 –

+1

为什么不看一下[Dispatcher](http://msdn.microsoft.com/zh-cn/library/system.windows.threading.dispatcher.aspx)类。这将允许您将数据传回您的UI线程。只是不要在另一个线程上创建UI元素并将它们传递过来,想想如何传递数据,而不是控件。 – Steve

回答

1

我在WPF中的一个单独的STA线程上创建一个控件,并且希望将它添加到列表中,然后使用list和itemssource作为itemcontrol。

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

问题是您需要创建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 
+0

好的,但问题是UI在填充列表时冻结了大约2到3分钟。图像是通过网络传送的高分辨率图像,大约有40张图像!我如何在不中断用户体验的情况下做到这一点? **无线网络** –

+0

@richardharrison查看我的评论。您可以在后台线程创建'ImageSource's,然后调用冻结()对他们 –

+0

好了,这样我就可以在后台线程创建一个列表(中ImageSource的),并调用.Freeze每个数据源上。然后回到UI线程使用List(Of ImageSource)创建控件? –

相关问题