將值從一個線程傳遞到另一個線程的最簡單的方法是利用文件。您將該值序列化爲一個文件,然後將其反序列化。因此,您必須使用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