WPF Set Owner on Window created on its own dedicated user interface thread

I have the following code that launches a WPF window on its own dedicated UI thread:

// Create the dedicated UI thread for AddEditPair window
Thread addEditPairThread = new Thread(() =>
{
    // Initialise the add edit pair window
    addEditPair = new AddEditPair(this);
    addEditPair.PairRecordAdded += new EventHandler<PairRecordEventArgs>(addEditPair_PairRecordAdded);
    addEditPair.PairRecordEdited += new EventHandler<PairRecordEventArgs>(addEditPair_PairRecordEdited);

    // Force AddEditPair to run on own UI thread
    System.Windows.Threading.Dispatcher.Run();
});
addEditPairThread.IsBackground = true;
addEditPairThread.Name = "AddEditPair";
addEditPairThread.SetApartmentState(ApartmentState.STA);
addEditPairThread.Start();

This works fine unless I try to set the owner of this window to a window that runs on the main Ui thread.

An exception I get:

The calling thread cannot access this object because a different thread owns it.

I understand what the error means and why this happens, so I implemented the following:

// If invoke is not required - direct call
if (addEditPair.Dispatcher.CheckAccess())
    method();
// Else if invoke is required - invoke
else
    addEditPair.Dispatcher.BeginInvoke(dispatcherPriority, method);

But I still get the same error. Now i'm confused!

Any ideas? Any help would be appreciated.

+3
source share
4 answers

, - , , .

Main Window :

private MainWindow _main;

public AddEditPair(MainWindow main)
    : base(false)
{
    InitializeComponent();

    // Initialise local variables
    _main = main;
}

public MainWindow Main
{
    get
    {
        return _main;
    }
}

.

-1

?

, , , , , ( , ), - , , .

WPF - , - Windows , "" ( ), , , , , .

, - :

  • - - , , .

  • , , , WILL ( ) - .

  • , .

  • , .

  • , - - .

. , , WPF, (: ). , .

+4

, user32.

     [DllImport("user32.dll")]
     static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);

  public static void SetOwnerWindowMultithread(IntPtr windowHandleOwned, IntPtr intPtrOwner)
  {
            if (windowHandleOwned != IntPtr.Zero && intPtrOwner != IntPtr.Zero)
            {
                SetWindowLong(windowHandleOwned, GWL_HWNDPARENT, intPtrOwner.ToInt32());
            }
 }

WPF:

 public static IntPtr GetHandler(Window window)
        {
            var interop = new WindowInteropHelper(window);
            return interop.Handle;
        }

, !

 var handler = User32.GetHandler(ownerForm);

        var thread = new Thread(() =>
        {
                var window = new DialogHost();
                popupKeyboardForm.Show();
                SetOwnerWindowMultithread(GetHandler(popupKeyboardForm), handler);
                Dispatcher.Run();
        });

        thread.IsBackground = true;
        thread.Start();

P.s. SetParent:

[DllImport("user32.dll", SetLastError = true)]
            static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
+1

Trying to set one window as the parent of a window in another thread is not possible in WPF without freezing windows (which I am not sure is possible), since each of the windows will not be able to access other data.

Is there a good reason to create windows on separate threads? Basically you should be good at creating windows at the same level and using background workers to handle long taks.

0
source

Source: https://habr.com/ru/post/1768185/


All Articles