-1

I have a c++ application and use clr to call the below c# method. Everything is going good except for one thing. As wpf window needs STA thread, I'm trying to create a new thread with STA state and start it. This makes the wpf window modeless, even if the window is started with show dialog. So I tried using thread.join() to make the caller thread to wait until the thread completes or window closes. using thread.join() shows server busy window after a few seconds. (I'm not doing any operation related to the internet in my application).

How to make the caller thread to wait until the window closes? or How to get rid of Server busy window?

        void ShowWindow()
        {
            _ownerHandle = Process.GetCurrentProcess().MainWindowHandle;
            Thread newWindowThread = new Thread(new ThreadStart(() =>
            {
                MyWpfWindow window = new MyWpfWindow();
                MyWpfWindowViewModel vm = new MyWpfWindowViewModel();

                WindowInteropHelper helper = new WindowInteropHelper(window);
                helper.Owner = _ownerHandle;

                window.DataContext = vm;

                window.ShowDialog();

            }));

            // set the apartment state  this will only invoke the WPF window  
            newWindowThread.SetApartmentState(ApartmentState.STA);
            newWindowThread.IsBackground = true;
            // start the thread  
            newWindowThread.Start();
            //waits this thread here untill the newWindowThread execution completes.
            newWindowThread.Join();

        }

Also, I tried with a while loop as below to block the current main thread.

while(!windowShown)
{
}

in the place of newWindowThread.join(). After using this, my window is not visible.

I'm getting a server busy window as below

enter image description here

bugfreerammohan
  • 1,471
  • 1
  • 7
  • 22
S.Frank Richarrd
  • 488
  • 1
  • 3
  • 15
  • Did you try to subclass `System.Window.Application`, configure it to use your Wpf window, and then call `Run()` on it? This is the proper way to boot a WPF Window. – Nick Mar 08 '19 at 12:20
  • Spawning a thread only to `Join it is kinda pointless –  Mar 08 '19 at 12:27
  • while (newWindowThread.IsAlive) { newWindowThread.Join(2000); } this solved my issue. now i'm not getting the server busy window also it behaves like blocking the current thread. Is it the way to block an MFC thread? – S.Frank Richarrd Mar 10 '19 at 18:12

1 Answers1

0

Calling Join() blocks the current thread. If you want to wait asynchronously, you could use a SemaphoreSlim:

static async Task ShowWindowAsync()
{
    SemaphoreSlim semaphore = new SemaphoreSlim(0, 1);
    _ownerHandle = Process.GetCurrentProcess().MainWindowHandle;
    Thread newWindowThread = new Thread(new ThreadStart(() =>
    {
        MyWpfWindow window = new MyWpfWindow();
        MyWpfWindowViewModel vm = new MyWpfWindowViewModel();
        WindowInteropHelper helper = new WindowInteropHelper(window);
        helper.Owner = _ownerHandle;
        window.DataContext = vm;
        window.Closed += (s, e) =>
        {
            semaphore.Release();
            semaphore.Dispose();
        };
        window.ShowDialog();

    }));

    // set the apartment state  this will only invoke the WPF window  
    newWindowThread.SetApartmentState(ApartmentState.STA);
    newWindowThread.IsBackground = true;
    // start the thread  
    newWindowThread.Start();
    //waits this thread here untill the newWindowThread execution completes.
    await semaphore.WaitAsync();
}
mm8
  • 163,881
  • 10
  • 57
  • 88