访问UI(主)在WPF中安全地线程

我有一个应用程序更新我的数据网格,每当我正在看日志文件更新(附加新文本)在以下方式:

private void DGAddRow(string name, FunctionType ft) { ASCIIEncoding ascii = new ASCIIEncoding(); CommDGDataSource ds = new CommDGDataSource(); int position = 0; string[] data_split = ft.Data.Split(' '); foreach (AttributeType at in ft.Types) { if (at.IsAddress) { ds.Source = HexString2Ascii(data_split[position]); ds.Destination = HexString2Ascii(data_split[position+1]); break; } else { position += at.Size; } } ds.Protocol = name; ds.Number = rowCount; ds.Data = ft.Data; ds.Time = ft.Time; dataGridRows.Add(ds); rowCount++; } ... private void FileSystemWatcher() { FileSystemWatcher watcher = new FileSystemWatcher(Environment.CurrentDirectory); watcher.Filter = syslogPath; watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName; watcher.Changed += new FileSystemEventHandler(watcher_Changed); watcher.EnableRaisingEvents = true; } private void watcher_Changed(object sender, FileSystemEventArgs e) { if (File.Exists(syslogPath)) { string line = GetLine(syslogPath,currentLine); foreach (CommRuleParser crp in crpList) { FunctionType ft = new FunctionType(); if (crp.ParseLine(line, out ft)) { DGAddRow(crp.Protocol, ft); } } currentLine++; } else MessageBox.Show(UIConstant.COMM_SYSLOG_NON_EXIST_WARNING); } 

当为FileWatcher引发事件时,因为它创build了一个单独的线程,当我尝试运行dataGridRows.Add(ds)时; 要添加新行,程序只是在debugging模式下没有任何警告崩溃。

在Winforms中,这很容易通过使用Invoke函数来解决,但我不知道如何在WPF中做这个。

您可以使用

Dispatcher.Invoke(Delegate, object[])

Application (或任何UIElement的)调度程序上。

你可以像这样使用它:

 Application.Current.Dispatcher.Invoke(new Action(() => { /* Your code here */ })); 

要么

 someControl.Dispatcher.Invoke(new Action(() => { /* Your code here */ })); 

最好的方法是从UI线程获取SynchronizationContext并使用它。 这个类将编组调用抽象为其他线程,并使testing更容易(与直接使用WPF的Dispatcher )。 例如:

 class MyViewModel { private readonly SynchronizationContext _syncContext; public MyViewModel() { // we assume this ctor is called from the UI thread! _syncContext = SynchronizationContext.Current; } // ... private void watcher_Changed(object sender, FileSystemEventArgs e) { _syncContext.Post(o => DGAddRow(crp.Protocol, ft), null); } } 

使用[Dispatcher.Invoke(DispatcherPriority,Delegate)]从另一个线程或从后台更改UI。

第1步 。 使用以下命名空间

 using System.Windows; using System.Threading; using System.Windows.Threading; 

第2步 。 将以下行放在需要更新UI的位置

 Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new ThreadStart(delegate { //Update UI here })); 

句法

 [BrowsableAttribute(false)] public object Invoke( DispatcherPriority priority, Delegate method ) 

参数

priority

types: System.Windows.Threading.DispatcherPriority

优先级相对于Dispatcher事件队列中的其他未决操作,将调用指定的方法。

method

types: System.Delegate

一个委托给没有参数的方法,它被推送到Dispatcher事件队列中。

返回值

types: System.Object

被调用的委托的返回值,如果委托没有返回值,则返回null。

版本信息

自.NET Framework 3.0起可用