阻止从其他线程启动WPF对话框

时间:2019-05-30 16:27:41

标签: wpf multithreading modal-dialog

我们要在主窗口上方创建并启动一个模式对话框框。由于某种原因,此过程是从其他线程启动的。这个不同的线程调用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();
}

任何想法如何实现此行为?预先感谢!

2 个答案:

答案 0 :(得分:0)

在不知道整个设置如何工作的情况下,这是一个简单的示例,说明如何利用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层进行交互的起点。

答案 1 :(得分:0)

You should shutdown the dispatcher when the dialog window is closed:

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);
}