WPF에서 안전하게 UI (기본) 스레드에 액세스
내가보고있는 로그 파일이 다음과 같은 방식으로 업데이트 (새 텍스트로 추가됨) 될 때마다 데이터 그리드를 업데이트하는 애플리케이션이 있습니다.
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에 대한 이벤트가 발생하면 별도의 스레드가 생성되므로 dataGridRows.Add (ds); 새 행을 추가하기 위해 프로그램은 디버그 모드 중에 경고없이 충돌합니다.
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 */ }));
The best way to go about it would be to get a SynchronizationContext
from the UI thread and use it. This class abstracts marshalling calls to other threads, and makes testing easier (in contrast to using WPF's Dispatcher
directly). For example:
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);
}
}
Use [Dispatcher.Invoke(DispatcherPriority, Delegate)] to change the UI from another thread or from background.
Step 1. Use the following namespaces
using System.Windows;
using System.Threading;
using System.Windows.Threading;
Step 2. Put the following line where you need to update UI
Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new ThreadStart(delegate
{
//Update UI here
}));
Syntax
[BrowsableAttribute(false)] public object Invoke( DispatcherPriority priority, Delegate method )
Parameters
priority
Type:
System.Windows.Threading.DispatcherPriority
The priority, relative to the other pending operations in the Dispatcher event queue, the specified method is invoked.
method
Type:
System.Delegate
A delegate to a method that takes no arguments, which is pushed onto the Dispatcher event queue.
Return Value
Type:
System.Object
The return value from the delegate being invoked or null if the delegate has no return value.
Version Information
Available since .NET Framework 3.0
참고URL : https://stackoverflow.com/questions/11625208/accessing-ui-main-thread-safely-in-wpf
'programing' 카테고리의 다른 글
모든 테이블 삭제 명령 (0) | 2020.10.11 |
---|---|
부동 소수점 숫자를 특정 소수점 자리로 반올림하는 방법은 무엇입니까? (0) | 2020.10.11 |
오류 : (6, 0) Gradle DSL 메서드를 찾을 수 없음 : 'google ()' (0) | 2020.10.11 |
`jupyter notebook` 실행시 오류 (해당 파일 또는 디렉토리 없음) (0) | 2020.10.11 |
매크로를 사용하여 Excel 통합 문서의 모든 피벗 테이블 새로 고침 (0) | 2020.10.11 |