将值从一个线程传递到另一个线程的最简单的方法是利用文件。您将该值序列化为一个文件,然后将其反序列化。因此,您必须使用System.Windows.Markup.XamlWriter/XamlReader
类将UserControl
保存到文件并将其加载回去。
下面的示例演示了这一点。您可以使用System.IO.Path.GetTempFileName()
方法保存到临时文件。
<Grid>
<Button Content="Create on new thread" HorizontalAlignment="Left" Margin="25,25,0,0" VerticalAlignment="Top" Width="126" Click="Button_Click_1"/>
<Button Content="Deserialize" HorizontalAlignment="Left" Margin="25,63,0,0" VerticalAlignment="Top" Width="126" Click="Button_Click_2"/>
<Label x:Name="Lbl" Margin="25,127,0,0" VerticalAlignment="Top" Height="105" Width="220"/>
</Grid>
代码:
private void Button_Click_1(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(() => { StartSTATask(create); });
}
bool create()
{
Button btn = new Button();
btn.Content = "Press me";
using (var stream = System.IO.File.Create(@"g:\\button.xaml"))
System.Windows.Markup.XamlWriter.Save(btn, stream);
return true;
}
public static Task<bool> StartSTATask(Func<bool> func)
{
var tcs = new TaskCompletionSource<bool>();
var thread = new Thread(() =>
{
try
{
var result = func();
tcs.SetResult(result);
}
catch (Exception e)
{
tcs.SetException(e);
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return tcs.Task;
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
using (var stream = System.IO.File.OpenRead(@"g:\\button.xaml"))
{
Button btn = System.Windows.Markup.XamlReader.Load(stream) as Button;
Lbl.Content = btn;
}
}
看到这个:http://stackoverflow.com/questions/12387687/is-it-possible-to-initialize-wpf-usercontrols-in-different-threads/ 12389044#12389044 ...当你使用任务...如果它计划在后台运行....它使用线程池线程...这将已经初始化与MTA(多线程公寓已经) 。一旦初始化到特定的公寓,它就不能改变......并且即使可以,也不想改变它的公寓,因为线程池中的线程被重用。 –
创建控件时花了那么长时间?一个控件通常不需要很长的时间来加载...控件是否可能加载了某种您可能能够单独加载的数据? – bassfader