Tengo una aplicación que actualiza mi cuadrícula de datos cada vez que se actualiza un archivo de registro que estoy viendo (se agrega con texto nuevo) de la siguiente manera:
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);
}
Cuando se genera el evento para el FileWatcher, porque crea un hilo separado, cuando intento ejecutar dataGridRows.Add (ds); para agregar la nueva fila, el programa simplemente se bloquea sin ninguna advertencia durante el modo de depuración.
En Winforms, esto se resolvió fácilmente utilizando la función Invoke, pero no estoy seguro de cómo hacerlo en WPF.
Application.Current
porque me parece más limpio.Dispatcher.BeginInvoke
. Ese método simplemente pone en cola al delegado para su ejecución.La mejor manera de hacerlo sería obtener una
SynchronizationContext
del hilo de la interfaz de usuario y usarlo. Esta clase abstrae las llamadas de clasificación a otros subprocesos y facilita las pruebas (en contraste con el usoDispatcher
directo de WPF ). Por ejemplo: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); } }
fuente
Utilice [Dispatcher.Invoke (DispatcherPriority, Delegate)] para cambiar la interfaz de usuario desde otro hilo o desde el fondo.
Paso 1 . Utilice los siguientes espacios de nombres
using System.Windows; using System.Threading; using System.Windows.Threading;
Paso 2 . Coloque la siguiente línea donde necesita actualizar la interfaz de usuario
Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new ThreadStart(delegate { //Update UI here }));
fuente