C# WPF可见性。从WPF按钮执行外部应用程序时,可见性不起作用;

C# WPF可见性。从WPF按钮执行外部应用程序时,可见性不起作用;,c#,wpf,multithreading,events,C#,Wpf,Multithreading,Events,我有以下代码来启动外部应用程序。当我点击按钮时,我需要使页面变灰,这样我就可以在页面上看到一个矩形,并且全屏显示 private void uxOfficeApps_Click(object sender, RoutedEventArgs e) { Rectangle rect = FindChild<Rectangle>(ParentWindow, "rectangle1"); rect.Height = _basePage.SCRE

我有以下代码来启动外部应用程序。当我点击按钮时,我需要使页面变灰,这样我就可以在页面上看到一个矩形,并且全屏显示

    private void uxOfficeApps_Click(object sender, RoutedEventArgs e)
    {
        Rectangle rect = FindChild<Rectangle>(ParentWindow, "rectangle1");
        rect.Height = _basePage.SCREEN_RESOLUTION_HEIGHT;
        rect.Width = _basePage.SCREEN_RESOLUTION_WIDTH;
        rect.Visibility = Visibility.Visible;

        string executablePath = _basePage.PATH_OFFICE;
        executable = new Process();
        executable.StartInfo.FileName = executablePath;
        executable.Start();
        executable.EnableRaisingEvents = true;
        executable.Exited += new EventHandler(officeApps_Exited);
        executable.WaitForExit();
   }
可见性不起作用

但是,当我在使矩形可见和创建流程对象之间放置MessageBox.Show(“警报”)时,它确实起作用


有人知道为什么吗???请帮助

尝试在Dispatcher.BeginInvoke中包装代码。这应该给UI足够的时间在您开始流程之前重新绘制

    Dispatcher.BeginInvoke(new Action(() =>
    {
        string executablePath = _basePage.PATH_OFFICE;
        executable = new Process();
        executable.StartInfo.FileName = executablePath;
        executable.Start();
        executable.EnableRaisingEvents = true;
        executable.Exited += new EventHandler(officeApps_Exited);
        executable.WaitForExit();
    }), DispatcherPriority.ApplicationIdle);

尝试在Dispatcher.BeginInvoke中包装代码。这应该给UI足够的时间在您开始流程之前重新绘制

    Dispatcher.BeginInvoke(new Action(() =>
    {
        string executablePath = _basePage.PATH_OFFICE;
        executable = new Process();
        executable.StartInfo.FileName = executablePath;
        executable.Start();
        executable.EnableRaisingEvents = true;
        executable.Exited += new EventHandler(officeApps_Exited);
        executable.WaitForExit();
    }), DispatcherPriority.ApplicationIdle);

由于您要求应用程序执行WaitForExit()ui线程挂起该操作。。。。因此,在进程退出之前,矩形可见性不会显示任何效果

使用以下代码

 new TaskFactory().StartNew(() =>
            {
 string executablePath = _basePage.PATH_OFFICE;
        executable = new Process();
        executable.StartInfo.FileName = executablePath;
        executable.Start();
        executable.EnableRaisingEvents = true;
        executable.Exited += new EventHandler(officeApps_Exited);
        executable.WaitForExit();
  });
在上面的代码中,我正在一个新任务中运行流程(就像后台一样)。。。。因此UI线程不会因进程退出而挂起

void officeApps_Exited(object sender, EventArgs e)
{
System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)delegate()
                 {
        MessageBox.Show("I am back");
        // do further processing
 });
}

您在“officeApps_Exited”中执行的任何操作都会将其移动到//进行进一步处理。

因为您要求应用程序执行WaitForExit()ui线程挂起该操作。。。。因此,在进程退出之前,矩形可见性不会显示任何效果

使用以下代码

 new TaskFactory().StartNew(() =>
            {
 string executablePath = _basePage.PATH_OFFICE;
        executable = new Process();
        executable.StartInfo.FileName = executablePath;
        executable.Start();
        executable.EnableRaisingEvents = true;
        executable.Exited += new EventHandler(officeApps_Exited);
        executable.WaitForExit();
  });
在上面的代码中,我正在一个新任务中运行流程(就像后台一样)。。。。因此UI线程不会因进程退出而挂起

void officeApps_Exited(object sender, EventArgs e)
{
System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)delegate()
                 {
        MessageBox.Show("I am back");
        // do further processing
 });
}

您在“officeApps_Exited”中所做的任何操作都会将其移动到//进行进一步处理。

我怀疑您的问题在于调用WaitForExit()会阻塞UI线程,因此会阻止呈现可见性更改。我不知道为什么设置一个MessageBox会有帮助,可能是由于与模式渲染有关的原因导致它在设置对话框之前重新绘制窗口。请尝试在BackgroundWorker中运行流程启动代码,然后使用Dispatcher.Invoke()在退出的事件处理程序中执行代码返回到UI线程。

我怀疑您的问题在于调用WaitForExit()会阻塞UI线程,从而阻止呈现可见性更改。我不知道为什么设置一个MessageBox会有帮助,可能是由于与模式渲染有关的原因导致它在设置对话框之前重新绘制窗口。请尝试在BackgroundWorker中运行流程启动代码,然后使用Dispatcher.Invoke()在退出的事件处理程序中执行代码返回到UI线程。

设置可见性不会导致显示刷新,它只是将其排队。您需要在启动外部应用程序之前强制重新绘制显示。我不熟悉如何在WPF中实现这一点,但我确信答案就在那里等着你;和rect.UpdateLayout();这没有什么区别,还有其他建议吗?设置可见性不会导致显示刷新,它只是将其排队。您需要在启动外部应用程序之前强制重新绘制显示。我不熟悉如何在WPF中实现这一点,但我确信答案就在那里等着你;和rect.UpdateLayout();这没有什么区别,还有其他建议吗?这很有效,但当我的函数返回时,我尝试关闭灰显图像,它说“调用线程无法访问此对象,因为其他线程拥有它。”你必须将officeapps_中退出的所有代码移到UI线程。。。我已经更新了答案,请看一看,这是可行的,但当我的函数返回时,我尝试关闭灰色图像,它说“调用线程无法访问此对象,因为其他线程拥有它。”你必须将officeapps_中退出的所有代码移到UI线程。。。我已经更新了答案,请看一看您的意思是如何使用Dispatcher.Invoke()在退出的事件处理程序中执行代码?你能举个例子吗。我遇到的问题是,在退出函数上,我试图隐藏矩形,但在使用线程运行时,我得到以下错误:“调用线程无法访问此对象,因为它是另一个线程拥有的。”在后台线程中运行时,在尝试触摸UI片段时,您将始终得到该错误,因此需要Dispatcher.Invoke()。我不知道如何在注释中编写格式化代码,但类似于:Dispatcher.Invoke(newaction(()=>{rect.Visibility=Visibility.Visibility;}));如何使用Dispatcher.Invoke()在退出的事件处理程序中执行代码?你能举个例子吗。我遇到的问题是,在退出函数上,我试图隐藏矩形,但在使用线程运行时,我得到以下错误:“调用线程无法访问此对象,因为它是另一个线程拥有的。”在后台线程中运行时,在尝试触摸UI片段时,您将始终得到该错误,因此需要Dispatcher.Invoke()。我不知道如何在注释中编写格式化代码,但类似于:Dispatcher.Invoke(newaction(()=>{rect.Visibility=Visibility.Visibility;}));