【问题标题】:Why don't delays work when I'm attempting to flash an error message?当我尝试闪现错误消息时,为什么延迟不起作用?
【发布时间】:2021-04-12 12:35:41
【问题描述】:

问题:我正在开发一个计算器作为我的第一个 MVVM 应用程序,并且遇到了一个我想更好地理解的有趣问题。我的菜鸟问题是我试图为无效输入闪烁错误消息——在这种情况下,我不希望用户在无效位置使用否定运算符。为了在屏幕上闪烁消息,我将显示保存在另一个变量中,将显示设置为“无效操作”,然后我想延迟半秒并将显示重置为之前的状态(来自临时变量)。我的问题是显示变量已设置但实际显示不会更新以显示错误消息,无论延迟多长时间。

我已经尝试过函数内的阻塞 (Thread.Sleep) 和非阻塞延迟 (Task.Delay),编写单独的函数来设置和重置显示,并在 Negate 内延迟函数,但这些尝试都不允许显示更新。在代码的其他部分添加和删除字符时,显示按预期工作,所以我认为这没有问题。

这是某种管道问题(延迟函数实际上是在它可以调用 Display 属性之前启动)还是完全是其他问题?我在这里查看了其他帖子,这些解决方案似乎无法解决我的问题。我很想得到反馈,说明为什么这不能像我期望的那样工作,以及更有效/更有效的编码方式。以下是相关代码块:

        public void Negate()
        {
            if (Display.Length > 0)
            {
                if (Display[Display.Length - 1].Equals('-'))
                {
                    Display = Display.Substring(0, Display.Length - 1);
                }
                else if (Display[Display.Length - 1].Equals(' ') || Display[Display.Length - 1].Equals('(') ||
                    Display[Display.Length - 1].Equals('E') || Display[Display.Length - 1].Equals('^'))
                {
                    Display += '-';
                }
                else
                {
                    InvalidOperation();
                }
            }
            else
            {
                Display = "-";
            }
        }
        public void InvalidOperation()
        {
            tempDisplay = Display;
            Display = "Invalid Operation";
            Thread.Sleep(500);
            Display = tempDisplay;
        }
        public string Display
        {
            get
            {
                return _display;
            }
            set
            {
                _display = value;
                OnPropertyChanged();
            }
        }

【问题讨论】:

  • 在 UI 线程上使用睡眠是一个坏主意 - 您的应用程序变得无响应,例如在睡眠呼叫中不能移动窗口。而是使用计时器来重置状态显示。

标签: c# delay display blocking


【解决方案1】:

UI 仅在方法 InvalidOperation 执行完成后才会更新,因为在方法的最后一行您将值设置回原始值 - UI 中没有更新。

异步方法应该可以工作,因为await 运算符将“暂停”InvalidOperation 方法并将执行返回到将更新 UI 控件的消息循环。

public async Task InvalidOperation()
{
    tempDisplay = Display;
    Display = "Invalid Operation";
        
    await Task.Delay(2000);

    Display = tempDisplay;
}

【讨论】:

  • 异步方法有效——谢谢。但是,我不太明白这个解释。我尝试将“无效操作”方法分成两半,以便以与设置位置不同的方法重置显示,但这不起作用。此外,“显示”是我一直用来设置显示的属性。它必须跳转到该属性来更新它,并且它具有 OnPropertyChanged() 足以满足任何其他更新显示的事件。
  • 基本上你不能在应用程序正在使用的同一线程上做任何事情,而它正在做某事。不过,我有一些东西可能对你有用。更新后尝试在显示控件上调用 .invalidate()。
  • 值和控件将更新为“临时”值,但实际 UI 仅在执行 Negate 方法后才会更新。异步方法“实际上”将其分解并在其间更新 UI
猜你喜欢
  • 2013-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
  • 2013-03-24
  • 2015-02-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多