【问题标题】:InvalidOperationException: dispatcher processing has been suspended, but messages are still being processedInvalidOperationException:调度程序处理已暂停,但消息仍在处理中
【发布时间】:2016-05-12 09:18:54
【问题描述】:

我们遇到了多个与此异常有关的问题,但我找不到有关问题真正原因的技术文档、此错误的所有可能来源以及我们应该避免什么以避免出现异常。

我已阅读以下内容:

调度程序处理被暂停以避免重入问题 更新可视化树时。

但我不确定“更新可视化树”是什么意思,以及是什么导致将消息发送到调度程序并重现问题。

以下示例代码重现了该问题:

XAML

<Window x:Class="SuspendedPOF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" 
        Height="350" 
        Width="525">
    <StackPanel>
        <Button Content="1" x:Name="Button1"  IsVisibleChanged="Button1_OnIsVisibleChanged" />
    </StackPanel>
</Window>

C#代码

using System.Windows;

namespace SuspendedPOF
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button1_OnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            MessageBox.Show("Hello");
        }
    }
}

MessageBox 调用并不是唯一触发此异常的调用,Focus 之类的调用有时也会出现问题。

任何帮助都会很棒。

【问题讨论】:

    标签: c# .net wpf dispatcher invalidoperationexception


    【解决方案1】:

    关键是您可能正试图在事件处理程序中更改按钮的视觉状态,该事件处理程序管理其视觉更改(即其可见性)。这可能导致无限循环(如您所读的“重入问题”),这也是您获得InvalidOperationException 的原因。

    为避免此问题,您必须使用 Dispatcher 延迟打开 MessageBox。然后在Button1_OnIsVisibleChanged方法中,使用这段代码:

    Dispatcher.BeginInvoke(new Action(() => System.Windows.MessageBox.Show("Hello")),
        System.Windows.Threading.DispatcherPriority.Normal);
    

    而不是直接调用MessageBoxShow静态方法。

    【讨论】:

    • 好的,但是我如何在开发时知道事件处理程序是有问题的处理程序之一,并且事件处理程序中的方法可以修改按钮的视觉状态?消息框看起来不能修改按钮的视觉状态
    • @IgnacioSolerGarcia 我相信您(或您的同事)应该问自己,处理控件的IsVisibleChanged 事件的代码是否正在尝试更改同一控件的视觉状态。我想没有别的办法了。例如,显示一个消息框可能会隐藏您的控件(考虑消息框是否显示在 right 上方)。在这种情况下你必须使用Dispatcher,否则你不需要。
    • 老实说,这听起来很疯狂。没有考虑到使用 BeginInvoke 启动事物会导致不同步,因此流程在执行之间可能会有所不同...
    • @IgnacioSolerGarcia,我很抱歉,但我不明白什么听起来很疯狂。您的意思是使用BeginInvoke 方法吗?
    • 不,我的意思是首先知道处理事件的代码是否最终在修改可视树的某些内容的潜在大调用树中结束,然后知道哪些事件管理每个控件的可视状态(包括第 3 方像 Telerik 或 DevExpress)
    【解决方案2】:

    据我所知,无法知道您何时处理可以修改控件视觉状态的事件,也无法知道您的操作是否会修改 UI 的视觉状态,所以它只是每当您发现崩溃时就放置BeingInvokes ...:S

    【讨论】:

      猜你喜欢
      • 2014-06-20
      • 2018-03-26
      • 2012-01-13
      • 2011-12-23
      • 2015-10-21
      • 2011-12-18
      • 1970-01-01
      • 2021-12-05
      • 2012-03-25
      相关资源
      最近更新 更多