阻止从不同线程启动 WPF 对话框

Blocking launch of WPF Dialog from a different thread

我们想在主 window 上创建并启动一个 模态对话框 框。这个过程是从不同的线程启动的——出于某种原因。这个不同的线程调用 execute 方法 - 并且必须被阻塞直到对话框关闭。问题是——如何?在此代码上,执行不会被阻止。 Join() 调用也没有按预期工作。

public void Execute()
{
    Thread newWindowThread = new Thread(new ThreadStart(ThreadStartingPoint));
    newWindowThread.SetApartmentState(ApartmentState.STA);
    newWindowThread.IsBackground = true;
    newWindowThread.Start();
    // newWindowThread.Join();
}


private void ThreadStartingPoint()
{
    this.ParameterDialog = new ParameterDialog();
    this.ParameterDialog.ShowDialog();
    System.Windows.Threading.Dispatcher.Run();
}

知道如何实现这种行为吗?提前致谢!

在不知道整个设置如何工作的情况下,这里是一个快速示例,说明如何利用 Dispatcher 从单独的线程与 UI 层进行交互。我使用 Microsoft wpf 库 here 中的示例作为我的起点。我去掉了一些不适用的代码。

MainWindow.xaml.cs

 public partial class MainWindow : Window
 {
    public delegate void NextPrimeDelegate();

    private bool _continueCalculating;

    private Action MyCallback = () => 
    {
        //****Carry out your Code (Execute) Here****
        var myPopup = new PopUp();
        myPopup.ShowDialog();
    };
    public MainWindow()
    {
        InitializeComponent();
    }

    private void StartOrStop(object sender, EventArgs e)
    {
        if (_continueCalculating)
        {
            _continueCalculating = false;
            startStopButton.Content = "Resume";
        }
        else
        {
            _continueCalculating = true;
            startStopButton.Content = "Stop";
            startStopButton.Dispatcher.BeginInvoke(
                DispatcherPriority.Normal,
                new NextPrimeDelegate(MyCallback));
        }
    }
}

MyPopUp.xaml

<Window x:Class="SingleThreadedApplication.PopUp"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:SingleThreadedApplication"
    mc:Ignorable="d"
    Title="PopUp" Height="200" Width="300">
<Window.CommandBindings>
    <CommandBinding Command="ApplicationCommands.Close"
                    Executed="CloseCommandHandler"/>
</Window.CommandBindings>

<Grid>
    <TextBlock Text="My Popup" HorizontalAlignment="Center" VerticalAlignment="Center"/>
    <Button Content="Close" HorizontalAlignment="Right" VerticalAlignment="Bottom" Command="ApplicationCommands.Close"/>
</Grid>

将此方法添加到 PopUp.xaml.cs

private void CloseCommandHandler(object sender, ExecutedRoutedEventArgs e)
{
   this.Close();
}

这有望为您提供一个起点,让您通过不同的线程与 UI 层进行交互。

您应该在对话框 window 关闭时关闭调度程序:

public void Execute()
{
    Thread newWindowThread = new Thread(new ThreadStart(ThreadStartingPoint));
    newWindowThread.SetApartmentState(ApartmentState.STA);
    newWindowThread.IsBackground = true;
    newWindowThread.Start();
    newWindowThread.Join();
}

private void ThreadStartingPoint()
{
    this.ParameterDialog = new ParameterDialog();
    this.ParameterDialog.Closed += ParameterDialog_Closed;
    this.ParameterDialog.ShowDialog();
    System.Windows.Threading.Dispatcher.Run();
}

private void ParameterDialog_Closed(object sender, EventArgs e)
{
    this.ParameterDialog.Closed -= ParameterDialog_Closed;
    Dispatcher.CurrentDispatcher.BeginInvokeShutdown(DispatcherPriority.Background);
}