0

I'm working on a project to integrate WPF Windows into a large application written in Visual FoxPro. The project has been progressing for a couple of years with success.

One downside to this project is the limitation of the UI thread. FoxPro is an STA app, so there is only one thread that both UI and application services must share. While the application is retrieving data, the UI is locked up. It is my hope that the method we're using to integrate WPF into this app gives us an opportunity to introduce a separate UI thread for the WPF Windows we're using.

How do we integrate WPF into a STA app?

We build a .NET COM server, not an ActiveX control. Instead we're using a simple COM control that exposes events. Our FoxPro client app subscribes to the events and handles UI requests through these events.

We start with a couple of .NET classes that the COM server will use.

// This class allows us to initialize an Application within a COM server
// since there is no App.xaml to do that for us.
[ComVisible(false)]
public class MyApp : System.Windows.Application
{ }

// This class allows us to assign the FoxPro app's main window as the owner
[ComVisible(false)]
public abstract class MyWindow : System.Windows.Window
{
  private System.Windows.Interop.WindowInteropHelper _helper;

  public void AssignOwner(int hWnd)
  {
    _helper = new WindowInteropHelper(this);
    _helper.Owner = new IntPtr(hWnd);
  }
}

The FoxPro app instantiates an instance of the COM server, subscribes to COM events, then calls a method to show the WPF window. The COM server's Show method first causes this bit of code to execute once per VFP app by delegating it to a static class.

if (Application.Current == null)
  _ = new MyApp();   

if (Application.Current != null)
{
  Application.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
  Application.Current.DispatcherUnhandledException += Application_DispatcherUnhandledException;
}

The Show method then builds a Window and displays it. There's nothing special here.

// Build a business model to access data and services through COM events
var model = new MyModel(this);
// ShellView is an implementation of MyWindow
var window = new ShellView { DataContext = new ShellViewModel(model) };
if (hWnd > 0)
  window.AssignOwner(hWnd);  && hWnd is a handle to the FoxPro window

window.Show();

The Question

Does the static code that builds the WPF Application instance give us the opportunity to construct a separate UI thread for the Dispatcher used by the WPF components?

RMart
  • 548
  • 1
  • 5
  • 20
  • Have you considered making the wpf an app that runs separately? You could communicate between the two using message queue, named pipes or the like. – Andy Sep 22 '21 at 18:53
  • @Andy Yes, we've successfully done that using named pipes. We use WCF heavily, so this is familiar territory. But the architecture for each window is more complex and the dev cost is too high, so we use this only when necessary, not for the entire system. I gotta admit, it's an appealing backup plan that works well. – RMart Sep 22 '21 at 20:50
  • See [Can/Does WPF have multiple GUI threads?](https://stackoverflow.com/questions/5716804/can-does-wpf-have-multiple-gui-threads) – Rekshino Sep 23 '21 at 07:22
  • @RMart: Did you try to create the `Application` on a separate STA thread? – mm8 Sep 23 '21 at 13:59
  • @mm8 It's been more than a year, but yes, creating an STA thread worked well. Much of the solution was built using the info from the answer Rekshino mentioned. – RMart Mar 28 '22 at 14:47

0 Answers0