如何在两个线程之间正确传递包含资源的 UserControl?
我已经尝试解决这个问题有一段时间了,但我只是被难住了。我创建了一个 UserControl 类型(在下面编辑),我试图从后台线程生成并序列化它。
生成Control的后台线程被标记为STA并使用内存流来传递控制。但是,该控件在 UserControl.Resources 部分中包含一个数据模板,该数据模板在反序列化期间会导致错误。
如果不在外部合并资源字典中定义资源,是否无法在线程之间传递包含资源的用户控件?
代码: UserControl:
<UserControl x:Class="WPF_Base.Example">
<UserControl.Resources>
<DataTemplate DataType={x:Type Example2}>
<Example2View />
</DataTemplate>
</UserControl.Resources>
<Grid>
<StackPanel>
<ItemsControl ItemSource="{Binding GetExamples}" />
</StackPanel>
</Grid>
</UserControl>
ThreadCode(呈现为单个线程):
System.IO.MemoryStream streamer = new System.IO.MemoryStream();
var testExample = new WPF_Base.Example();
var test = System.Windows.Markup.XamlWriter.Save(testExample);
var test2 = new System.IO.StringReader(test);
var test3 = System.Xml.XmlReader.Create(test2);
var test4 = (WPF_Base.TestExample)System.Windows.Markup.XamlReader.Load(test3); //Exception thrown here about key already existing in the dictionary
编辑: 这些控件是在另一个线程中生成和构建的,因为用户可能正在加载一个包含许多数据片段的文件(控件采用 MVVM 模式),每个数据片段都表示为屏幕上的视图。在此过程中,我仍然希望 UI 能够响应并且不会出现“锁定”。我想当控件渲染到屏幕上时我可能会错开,而不是一次全部渲染,因为这将是视图的主要瓶颈。
I have been trying to figure out this problem for a while now and am just stumped. I have created a UserControl type (edited below) that i am trying to generate and serialize from a background thread.
The background thread generating the Control is marked as STA and uses a memory stream to pass the control. However the control contains a data template in the UserControl.Resources section that is causing errors during deserialization.
Is it not possible to pass a user control containing a resource between threads without defining the resources in an external merged resource dictionary?
code:
UserControl:
<UserControl x:Class="WPF_Base.Example">
<UserControl.Resources>
<DataTemplate DataType={x:Type Example2}>
<Example2View />
</DataTemplate>
</UserControl.Resources>
<Grid>
<StackPanel>
<ItemsControl ItemSource="{Binding GetExamples}" />
</StackPanel>
</Grid>
</UserControl>
ThreadCode (Presented as a single thread):
System.IO.MemoryStream streamer = new System.IO.MemoryStream();
var testExample = new WPF_Base.Example();
var test = System.Windows.Markup.XamlWriter.Save(testExample);
var test2 = new System.IO.StringReader(test);
var test3 = System.Xml.XmlReader.Create(test2);
var test4 = (WPF_Base.TestExample)System.Windows.Markup.XamlReader.Load(test3); //Exception thrown here about key already existing in the dictionary
EDIT:
The controls are being generated and built in the other thread for due to the possibly that user may be loading a file that contains many pieces of data (controls are in a MVVM pattern) that each are represented as a view on the screen. During this process i would still want the UI to be responsive and not appear to "lock". I guess i could stagger when the controls are rendered to the screen instead of all at once since that would be the major bottle neck with the views.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
编辑:
如果您确实使用 MVVM 模式,则应该在主 (UI) 线程上创建控件,在另一个线程上创建对象数据,并在可用时将其设置为控件的 DataContext。更好的是,在每个“DataContext”可用之前根本不要创建控件。这是保持应用程序响应的常用方法,即使您可能需要等待很长时间才能获取数据(例如通过互联网)。
老-->关于你的问题的第一部分:
这不是线程问题。简而言之,这是行不通的,因为当您尝试反序列化数据时,运行时会再次尝试将模板添加到对象的内部“XAMLType”表示形式中。然而,这种效果不仅限于模板,当您尝试以这种方式加载它时,您定义的任何资源都会导致问题。即使为控件中的 XAML 元素提供名称等也会导致问题。
编辑:
您尝试使用的 XAML 序列化器方法并非其预期用途。此外,由于您在评论中提到的原因,您不想在另一个线程上创建控件。
EDIT:
If you are indeed using the MVVM pattern, you should create your control on the main (UI) thread, create your object data on the other thread, and set it as the control's DataContext when it is available. Better yet, don't create the control at all until each 'DataContext' becomes available. This is a common way to keep your application responsive even when you may have to wait a long time for the data, say over the internet.
OLD --> About the first part of your question:
This isn't a threading problem. In short, this is not working because when you try to deserialize the data, the runtime is trying to add the template, again, to the internal 'XAMLType' representation of your object. This effect is not limited to templates however, any resource that you define will cause a problem when you attempt to load it in this fashion. Even giving names, etc. to XAML elements in your control will cause problems.
EDIT:
The XAML serializer approach that you are trying to use is not what it is intended for. Additionally, you don't want to create controls on another thread for the reason that you mention in you comment.