如何在繁忙的过程中快速处理事件,有更新命令吗
本文关键字:处理事件 更新 命令 过程中 | 更新日期: 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的东西。