I'd love to know the why behind your unique situation. I'm assuming that the Dispatcher is associated with the same thread on which parentStackPanel
is created. WPF controls have thread-affinity and all of them must be modified from the same thread. You are constructing a Label
object which in your first example, is constructed in the same thread as the StackPanel
which is good. In your second example, it is constructed on a different thread which is most likely why the code is not working. Attach with a debugger and you ought to catch some sort of exception being thrown.
Using System.AddIn's FrameworkElementAdapters in background threads
-
13-10-2022 - |
سؤال
Without getting too much into the "why" I need to do this, here is my situation. I need to create an INativeHandleContract to pass a UserControl over an AppDomain boundary, from a new AppDomain into the main AppDomain, where it is then added to a StackPanel. But I am also trying to do this in a different thread. I ran in to a situation where it appears the UserControl is being added correctly if this all runs in the same thread. If I add the UserControl to the StackPanel from a separate thread, it seems to get added but nothing appears on screen. So I boiled this down to the following code and found where the difference is. First the working code:
private void AddTestControlInNewThread()
{
System.Threading.Thread t = new System.Threading.Thread(AddTestControl);
t.SetApartmentState(System.Threading.ApartmentState.STA);
t.Start();
}
private void AddTestControl()
{
INativeHandleContract contract;
FrameworkElement fe;
Dispatcher.Invoke(new Action(() =>
{
contract = FrameworkElementAdapters.ViewToContractAdapter(new Label() { Content = DateTime.Now.ToString() });
fe = FrameworkElementAdapters.ContractToViewAdapter(contract);
parentStackPanel.Children.Add(fe);
}), null);
}
That works just fine, however, in my scenario, I cannot create the "contract" inside of the Dispatcher.Invoke call. So I moved it to just outside of that and that's where thing stop working. Here is the difference in code:
private void AddTestControl()
{
INativeHandleContract contract;
FrameworkElement fe;
contract = FrameworkElementAdapters.ViewToContractAdapter(new Label() { Content = DateTime.Now.ToString() });
Dispatcher.Invoke(new Action(() =>
{
fe = FrameworkElementAdapters.ContractToViewAdapter(contract);
parentStackPanel.Children.Add(fe);
}), null);
}
Can anyone shine some light on why the user control would not show up, even if it does get added to the parentStackPanel's Children collection successfully? Thanks in advance.
المحلول