如何在繁忙的过程中快速处理事件,有更新命令吗

本文关键字:处理事件 更新 命令 过程中 | 更新日期: 2023-09-27 18:20:43

在一个漫长(约1分钟)的过程中,我试图通过向文本控件写入带时间戳的消息来记录一些进度。但所有信息同时出现。显然,所有的PropertyChanged events都在排队,直到我的繁忙进程完成,并由文本控件同时接收。我如何才能在繁忙的过程中"冲洗"事件?我进行了搜索,但找不到立即处理排队事件的Flush/Update/Dispatch调用。

多线程解决方案是有问题的1194620,但如果可能的话,我首先希望避免多线程。在较旧的环境(C++、.Net Winforms/ASP)中,总是有像Update这样的系统调用来中断繁忙的进程以处理挂起的事件。

编辑:请不要告诉我一个漫长的过程应该在另一个线程中。我同意。但这是继承的代码,在我考虑转换为多线程之前,我首先需要记录某些事件来了解它的作用。此外,该应用程序还有许多其他问题需要首先解决。此外,在解决了问题后,漫长的过程可能不再漫长。

我在问题18888937中发现了从代码中的任何位置编写字符串的方法,并且效果良好。

这是背后的代码。编辑:我在"已接受应答"中将呼叫添加到解决方案中。

public partial class App : Application, INotifyPropertyChanged
{
    /// <summary>
    /// Property for the log message for the TextBlock control
    /// </summary>
    public string StartupMessage
    {
        get { return _StartupMessage; }
        set
        {
            if (_StartupMessage.Length == 0)
            {
                _StartupMessage = string.Format("{0:HH-mm-ss} {1}", 
                                          DateTime.Now, value);
            }
            else
            {
                _StartupMessage = string.Format("{0}{1}{2:HH-mm-ss} {3}",
                  _StartupMessage, Environment.NewLine, DateTime.Now, value);
            }
            OnPropertyChanged("StartupMessage");
        }
    }
    private string _StartupMessage = "";
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
            DoEvents();//see the accepted answer below
        }
    }

这是文本控件:

<TextBlock x:Name="textblock_StartupMessages" 
             Margin="10" TextWrapping="Wrap" 
  Text="{Binding Path=StartupMessage, Source={x:Static Application.Current}}">
</TextBlock>

下面是我如何在代码中放置来自另一个位置的消息:

public class AllRoutesViewModel : ViewModelBase
{
    public AllRoutesViewModel()
    {
        (System.Windows.Application.Current as App).StartupMessage = 
                                           "start of AllRoutesViewModel()";

如何在繁忙的过程中快速处理事件,有更新命令吗

尽可能避免多线程。在较旧的环境中(C++、.NetWinforms/ASP)总是有像Update这样的系统调用来中断处理未决事件的繁忙进程。

这是在一个系统上尝试一种设计模式,该系统被设计为而不是,其行为与您提到的系统类似。

不应在WPF中的GUI线程上执行长时间运行的操作。

Notify属性更改仅在GUI线程未被阻止时有效,因为它本质上是一个GUI进程。您所拥有的代码正在阻塞GUI线程。如果在后台工作程序中正确地运行任务,或者异步任务并正确地更新属性,则通知将使GUI在视觉上按照您实际想要和期望的方式运行。

但根据您提出的设计,以图形方式这样做是不可能的。最好的答案是学习WPF设计模式并遵循它,而不是强制使用不同的技术设计模式。

您可以考虑使用Dispatcher.PushFrame.

有关该课程的更多信息,请点击此处。

此外,以下是MDSN的相关代码示例(稍作修改):

using System.Windows.Threading;  //DispatcherFrame, needs ref to WindowsBase
//[SecurityPermissionAttribute(SecurityAction.Demand, Flags =   SecurityPermissionFlag.UnmanagedCode)]
public void DoEvents()
{
    DispatcherFrame frame = new DispatcherFrame();
    Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
        new DispatcherOperationCallback(ExitFrame), frame);
    Dispatcher.PushFrame(frame);
}
public object ExitFrame(object f)
{
    ((DispatcherFrame)f).Continue = false;
    return null;
}

虽然在这种情况下,这个解决方案可能会给你想要的东西,但我必须同意其他人对设计模式的看法。请在未来考虑类似MVVM的东西。