What's the best way to create a new UI thread and call back methods on the original thread?

你。 提交于 2021-02-11 12:49:35

问题


I'm writing a plug-in class for a third-party GUI application. The application calls the Run method of my class, passing me a vendor-defined Context object. Any methods or properties in this Context object must be called from the current thread (that is, the application's UI thread).

My plug-in code creates a WPF Window and shows it to the user. Some interactions need to call the Context object's methods, but some take time to run. This, of course, freezes my UI. Normally, I would call slow methods from a separate thread, but in this case I can't do that because the Context object is tied to the application's UI thread.

Here's an example implementation of my Plugin class:

public class Plugin
{
    public void Run(Context context)
    {
        // Create a window with my custom user interface
        var window = new MyWindow();

        // Call a slow method when MyButton is clicked
        window.MyButton.Click += (o, e) => context.SlowMethod();

        // Prevent exiting this Run method until the window is closed
        window.ShowDialog();
    }
}

What are some possible solutions that would allow me to call slow methods in the Context object (bound to the UI thread) while having a responsive UI?

One solution I've come up with is to create a second thread on which to run my UI and use the original thread to call Context methods. However, my implementation is rather complex, so I'd like to know if there's a more straightforward way to achieve this.

Here's my current solution:

public class Plugin
{
    public void Run(Context context)
    {
        // Get the application's UI thread dispatcher
        var dispatcher = Dispatcher.CurrentDispatcher;

        // Create a dispatcher frame to push later
        var frame = new DispatcherFrame();

        // Create a new UI thread (using an StaTaskScheduler)
        Task.Factory.StartNew(async () =>
        {
            var window = new MyWindow();

            // The Click event handler now uses the original
            // thread's dispatcher to run the slow method
            window.MyButton.Click += async (o, e) =>
                await dispatcher.InvokeAsync(() => context.SlowMethod());

            window.ShowDialog();

            // When the window is closed, end the dispatcher frame
            frame.Continue = false;
        }, CancellationToken.None, TaskCreationOptions.None, new StaTaskScheduler(1));

        // Prevent exiting this Run method until the frame is done
        Dispatcher.PushFrame(frame);
    }
}

The StaTaskScheduler schedules tasks in an STA thread (as required by WPF). It comes from the Parallel Extensions Extras library.

来源:https://stackoverflow.com/questions/56794412/whats-the-best-way-to-create-a-new-ui-thread-and-call-back-methods-on-the-origi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!