如何在wpf中的线程中打开第二个窗口后关闭窗口?

问题描述 投票:0回答:1

我创建了一个等待窗口,该窗口保持打开状态以查看软件加载情况。当软件完成计算后,它打开主窗口...我想关闭等待窗口...

所以我找到了这段代码

Thread thread = new Thread(() =>
{

 PopupAtt proc = new();
 proc.Show();

 proc.Closed += (sender2, e2) =>
  proc.Dispatcher.InvokeShutdown();
 proc.Owner = Window.GetWindow(this);
 System.Windows.Threading.Dispatcher.Run();
 
 });

 thread.SetApartmentState(ApartmentState.STA);
 thread.Start();
 thread.IsBackground = true;

要创建线程并且运行良好,它会打开带有加载百分比的等待窗口,然后主窗口打开,但不会关闭等待窗口...... 我没有找到关闭等待窗口线程的方法,但只有当整个程序关闭时它才会关闭。 如何只关闭等待窗口?

c# wpf multithreading dispatcher
1个回答
0
投票

分析

WPF 中,与来自多种编程语言的许多其他 UI 框架一样,将启动应用程序的线程分配为 UI 线程。

// SUPERFLUOUS THREAD INVOCATION
Thread thread = new Thread(() =>
{

 PopupAtt proc = new();
 proc.Show();

 proc.Closed += (sender2, e2) =>
  proc.Dispatcher.InvokeShutdown();
 proc.Owner = Window.GetWindow(this);

 // SUPERFLOUS MIGRATION OF THE CURRENT THREAD PROCESS TO THE UI THREAD
 System.Windows.Threading.Dispatcher.Run();
 
});

thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.IsBackground = true;

正如我所指出的,线程对象的创建以及将其操作迁移到 UI 线程是多余的,这意味着整个操作是不必要的。

解决方案

WPF应用程序的核心机制是,只要打开一个窗口,应用程序就会继续运行。打开窗口的主要机制是从实现窗口对象的类中实例化一个对象,然后调用 Show()

ShowDialog()
。这两者之间的区别在于 
Show()
 将打开一个独立于父窗口的窗口,而 
ShowDialog()
 将打开一个依赖于父窗口的窗口,并且这也会阻止用户与父窗口交互直到当前子窗口关闭。您的问题所需的机制是在应用程序启动时启动正在处理计算的窗口,并在计算完成后打开主窗口并关闭执行计算的窗口。

首先,执行计算的窗口必须设置为在应用程序启动时启动。这可以通过将 App.xaml 文件中的

StartupUri

 参数设置为正在执行计算的窗口的名称来完成,在本例中为 
Processing

<!-- App.xaml --> <Application x:Class="StackOverflow.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:StackOverflow" StartupUri="Processing.xaml"> <Application.Resources> </Application.Resources> </Application>
其次,窗口执行计算后,必须实例化主窗口对象中的一个对象,必须使用 

Show()

 方法创建窗口,然后必须关闭当前窗口。最好在窗口加载时启动计算。为此,只需在 
XAML
 部分中使用窗口对象的 
Loaded 属性,并为此 Loaded 事件 提供方法名称

<!-- Processing.xaml --> <Window x:Class="StackOverflow.Processing" 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:StackOverflow" mc:Ignorable="d" Title="Processing" Height="450" Width="800" Loaded="Calculate_the_values" > <Grid> <TextBlock x:Name="Calculate_Label" HorizontalAlignment="Center" VerticalAlignment="Center" Text="Calculate the values" FontSize="40"/> </Grid> </Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace StackOverflow
{
    // Processing.cs

    /// <summary>
    /// Interaction logic for Processing.xaml
    /// </summary>
    public partial class Processing : Window
    {
        private int percent = 0;
        public Processing()
        {
            InitializeComponent();
        }

        // LOADED EVENT
        private void Calculate_the_values(object sender, RoutedEventArgs e)
        {

            System.Timers.Timer timer = new System.Timers.Timer();
            timer.Elapsed += Timer_Elapsed;
            timer.Interval = 200;
            timer.Start();

        }

        private async void Timer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
        {
            percent += 10;
            await Application.Current.Dispatcher.InvokeAsync(() =>
            {

                Calculate_Label.Text = $"Progress: {percent}%";
                if (percent == 100)
                {
                    new MainWindow().Show();
                    this.Close();
                    ((System.Timers.Timer?)sender)?.Dispose();
                }
            });
        }
    }
}

<!--
    MainWindow.xaml
-->

<Window x:Class="StackOverflow.MainWindow"
        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:StackOverflow"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800" Loaded="Window_Loaded" Background="Green">
    <Grid>
        <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="50" FontWeight="Bold" Foreground="White" Text="Main Window"/>
    </Grid>
</Window>

using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace StackOverflow
{
    // MainWindow.cs

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        Processing processing = new Processing();

        public MainWindow()
        {
            InitializeComponent();
        }

        public MainWindow(Processing _processing)
        {
            InitializeComponent();
            processing = _processing;
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            processing.Close();
        }
    }
}

Application output example

© www.soinside.com 2019 - 2024. All rights reserved.