C# UI事件如何到达WPF调度程序?

C# UI事件如何到达WPF调度程序?,c#,.net,wpf,multithreading,dispatcher,C#,.net,Wpf,Multithreading,Dispatcher,我正在开发的当前应用程序是另一个商业应用程序的插件。在我的插件中,我可以使用Execute()方法创建一个自定义Command类,当用户决定运行自定义命令时,父应用程序将调用该方法 此API提供的对象不是线程安全的,因此我只能从应用程序启动的Execute()线程访问它们。但是,我尝试执行的一些任务需要一段时间才能完成,我希望向用户显示一个进度窗口 我可以通过启动另一个线程来显示窗口,从而创建一个功能正常、响应迅速的进度窗口。这要求我手动启动该线程的WPF调度程序,如中所述 我可以在进程进行时拖

我正在开发的当前应用程序是另一个商业应用程序的插件。在我的插件中,我可以使用
Execute()
方法创建一个自定义
Command
类,当用户决定运行自定义命令时,父应用程序将调用该方法

此API提供的对象不是线程安全的,因此我只能从应用程序启动的
Execute()
线程访问它们。但是,我尝试执行的一些任务需要一段时间才能完成,我希望向用户显示一个进度窗口

我可以通过启动另一个线程来显示窗口,从而创建一个功能正常、响应迅速的进度窗口。这要求我手动启动该线程的WPF调度程序,如中所述

我可以在进程进行时拖动此窗口。但是,如果在任务运行时与窗口内的任何内容进行交互,例如单击窗口,它将冻结

我发现,如果我在实际的
命令.Execute()
线程中实例化并显示一个WPF窗口,那么该窗口在命令退出后将保持可见和响应。因此,本机程序似乎有一个WPF调度程序在命令线程上运行。我通过从
Execute()
连接到
Dispatcher.CurrentDispatcher.Hooks.OperationPosted
验证了这一点。当我与本机应用程序交互时,
Execute()
方法退出后,它继续发送消息

因此,我认为正在发生的是,当我单击窗口时,本机应用程序的调度程序正在处理这个单击。这个调度程序不知道我的窗口,甚至无法访问它,因为它是在另一个线程中创建的。此外,该调度器无论如何也无法执行任何操作,因为它的关联线程在执行耗时任务的
Execute()
方法中很忙

那么,有人能解释一下,点击WPF对象或以其他方式与WPF对象交互最终是如何将其添加到相关的调度程序队列中的吗?是否有某种方法可以重定向此消息,以便当用户单击我的进度窗口时,事件get被发送到正确的调度程序

更新 下面是一些示例代码,我一直在使用这些代码试图弄清楚到底发生了什么

当用户调用我的自定义命令时,本机应用程序将调用
Command.Execute()
。ProgressWindow只是一个带有ProgressBar和按钮的简单窗口。按钮只是有一个空的onClick处理程序,我在其中设置了一个断点

WorkerClass.DoWork()
在另一个线程上打开一个
ProgressWindow
。然后,它通过在for循环中循环,在每次迭代时更新窗口中的进度条来做一些虚假的工作

public class Command
{
    public void Execute()
    {
        Thread.CurrentThread.Name = "Command Thread";
        WorkerClass.DoWork();
    }
}

public class WorkerClass
{
    //Creates the new progress window thread
    public static void DoWork()
    {
        Thread newprogWindowThread = new Thread(new ThreadStart(ShowProgressWindow));
        newprogWindowThread.Name = "Progress Window Thread";
        newprogWindowThread.SetApartmentState(ApartmentState.STA);
        newprogWindowThread.IsBackground = true;
        
        //Starts New Progress Window Thread
        using (_progressWindowWaitHandle = new AutoResetEvent(false))
        {
            //Starts the progress window thread
            newprogWindowThread.Start();

            //Wait for progress window thread to notify that the window is up
            _progressWindowWaitHandle.WaitOne();
        }

        //Do some fake work
        for (int i = 1; i <= 100; i++)
        {
            //Do Some work
            Thread.Sleep(100);

            //Updates the progress window
            //This method queues the update to the 
            //actual Dispatcher of the window.
            progWindow.UpdateStatus("Item " + i.ToString(), i, 100);
        }


            MessageBox.Show("Work Finished");
     
    }

    private static ProgressWindow progWindow;
    internal static EventWaitHandle _progressWindowWaitHandle;

    private static void ShowProgressWindow()
    {
        //Creates and shows progress window
        progWindow = new ProgressWindow("Running Task...");
        progWindow.Show();

        //Subscribes to window closed event
        progWindow.Closed += progWindow_Closed;

        //Notifies other thread the progress window is open when the dispatcher starts up
        System.Windows.Threading.Dispatcher.CurrentDispatcher.BeginInvoke(new Func<bool>(_progressWindowWaitHandle.Set));

        //Starts the WPF dispatcher
        System.Windows.Threading.Dispatcher.Run();
    }

    private static void progWindow_Closed(object sender, EventArgs e)
    {
        //When window is closed shuts down WPF dispatcher
        //this will release thread from Dispatcher.Run() above
        //and exit the ShowProgressWindow() method and exit the secondary thread
        ProgressWindow window = (ProgressWindow)sender;
        window.Dispatcher.BeginInvokeShutdown(DispatcherPriority.Normal);
    }
}
公共类命令
{
public void Execute()
{
Thread.CurrentThread.Name=“命令线程”;
WorkerClass.DoWork();
}
}
公营工人班
{
//创建新的进度窗口线程
公共静态无效工作()
{
线程newprogWindowThread=新线程(新线程开始(ShowProgressWindow));
newprogWindowThread.Name=“进度窗口线程”;
newprogWindowThread.SetApartmentState(ApartmentState.STA);
newprogWindowThread.IsBackground=true;
//启动新的进度窗口线程
使用(_progressWindowWaitHandle=new AutoResetEvent(false))
{
//启动进度窗口线程
newprogWindowThread.Start();
//等待进度窗口线程通知窗口已打开
_progressWindowWaitHandle.WaitOne();
}
//做些假工作

对于(int i=1;识别号)。所有WPF UI元素都派生自
DispatcherObject
,并引用“它们的”
Dispatcher
。它们不能对无关的
Dispatcher
s进行操作,也不能相互关联,甚至不能被无关的
Dispatcher操作。我仍然不清楚您描述的场景。另外,请记住
Dispatcher。如果当前线程不存在任何Dispatcher,则CurrentDispatcher
将创建一个新的Dispatcher,从而调用
Dispatcher.CurrentDispatcher
从后台线程将不会返回对预期Dispatcher实例的引用。是的,我知道我从matters调用CurrentDispatcher的线程。我从Execute()调用它方法。不是我的第二个线程。谢谢!您能澄清您的问题或添加示例代码吗?@HighCore请参阅我的Updatery,不要创建创建窗口背景的线程(newprogWindowThread.IsBackground=true;),据我所知,消息队列仅为前台线程创建