Easiest way to pass a value from one thread to another is to make use of files. You serialize the value to a file, and then you deserialize it. So, you have to use System.Windows.Markup.XamlWriter/XamlReader
classes to save the UserControl
to a file and load it back.
Below sample demonstrates this. You can use System.IO.Path.GetTempFileName()
method for saving to a temp file.
<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>
Code :
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;
}
}