InvokeRequired and BeginInvoke equivalent
本文关键字:equivalent BeginInvoke and InvokeRequired | 更新日期: 2023-09-27 17:55:10
我的Windows窗体中有这个函数,现在我正在尝试将我的工作转移到WPF,传输后,我注意到 WPF 不支持InvokeRequired
和BeginInvoke
。 我正在寻找将我的函数转换为 WPF 的正确方法:
delegate void DisplayInvoker(string text, MessageType type);
private void DisplayinRichbox(string text, MessageType type = MessageType.Normal)
{
if (this.InvokeRequired) // not support by WPF
{
this.BeginInvoke(new DisplayInvoker(DisplayinRichbox), text, type); // Not support by WPF
return;
}
txt_Log.AppendText(String.Format("[{0}] {1}{2}'r'n",
DateTime.Now, type == MessageType.Incoming ? "<< " : type == MessageType.Outgoing ? ">> " : "", text));
txt_Log.ScrollToCaret(); // not support by WPF
}
这是我在主类中的线程循环:
while (bWaiting == true)
{
//System.Windows.Forms.Application.DoEvents(); // i comment it because i cant find equivalent in WPF
System.Threading.Thread.Sleep(15);
}
WPF 中的等价项是 Dispatcher.CheckAccess 和 Dispatcher.BeginInvoke:
if (!this.Dispatcher.CheckAccess())
{
this.Dispatcher.BeginInvoke(new Action(() => DisplayInRichbox(text, type)));
return;
}
编辑:
RichTextBox
从不更新的原因是你阻止了 UI 线程:
while (bWaiting == true)
{
//System.Windows.Forms.Application.DoEvents(); // i comment it because i cant find equivalent in WPF
System.Threading.Thread.Sleep(15);
}
这将阻止 UI 中的任何内容更新,因为您阻止它并且永远不会提供正确更新的方法。 在您的旧 Win Forms 代码中,您调用了 DoEvents()
,它处理消息(但由于许多原因,这是一个非常糟糕的主意)。 如果没有该调用,这将无法正常工作。
阻塞和循环 - 相反,在后台线程中执行工作,并让 UI 线程正常运行。 BackgroundWorker
使这变得更加简单,TPL中的许多选项也是如此。
里德·科普西 给了你问题的完整答案。但是,我只想指出,实际上您在 WPF 中不需要它。通常,当您通过 INotifyPropertyChanged
和 xaml 数据绑定使用 MVVM 模式时,会自动处理它。在同步集合的情况下,您可以使用多线程可观察集合。这是我自己使用的源代码。
public class MultiThreadedObservableCollection<T> : ObservableCollection<T> {
public override event NotifyCollectionChangedEventHandler CollectionChanged;
public MultiThreadedObservableCollection() { }
public MultiThreadedObservableCollection(IEnumerable<T> source) : base(source) { }
public MultiThreadedObservableCollection(List<T> source) : base(source) { }
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) {
var handle = CollectionChanged;
if (CollectionChanged == null)
return;
foreach (NotifyCollectionChangedEventHandler handler in handle.GetInvocationList()) {
var dispatcherObj = handler.Target as DispatcherObject;
if (dispatcherObj != null) {
var dispatcher = dispatcherObj.Dispatcher;
if (dispatcher != null && !dispatcher.CheckAccess()) {
dispatcher.BeginInvoke(
(Action)(() => handler.Invoke(
this,
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset))
), DispatcherPriority.DataBind);
continue;
}
}
handler.Invoke(this, e);
}
}
}
(它来自这里,stackoverflow.com 但现在找不到来源)
然后,您只需定义视图模型并开始更改值即可。这是开发 WPF 应用程序最合适、最正确且最快速的方法。