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);
}
DataGridRows를 실행하려고 하면 별도의 스레드가 생성되기 때문에 FileWatcher에 대해 이벤트가 발생할 때 발생합니다.Add(ds); 새 행을 추가하기 위해 프로그램은 디버깅모드 중에 경고 없이 크래시 됩니다.
Winforms에서는 Invoke 기능을 사용하면 쉽게 해결할 수 있었지만 WPF에서는 어떻게 해야 할지 잘 모르겠습니다.
사용할 수 있습니다.
Dispatcher.Invoke(Delegate, object[])
에서Application
(또는 임의의)UIElement
s) 디스패처
예를 들어 다음과 같이 사용할 수 있습니다.
Application.Current.Dispatcher.Invoke(new Action(() => { /* Your code here */ }));
또는
someControl.Dispatcher.Invoke(new Action(() => { /* Your code here */ }));
이 문제를 해결하는 가장 좋은 방법은 이 문제를 해결하는 것입니다.SynchronizationContext
UI 스레드에서 가져와 사용합니다.이 클래스는 다른 스레드에 대한 콜을 추상화하여 테스트를 용이하게 합니다(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);
}
}
[디스패처]를 사용합니다.다른 스레드 또는 백그라운드에서 UI를 변경하려면 (DispatcherPriority, 위임)을 호출합니다.
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
유형:
System.Windows.Threading.DispatcherPriority
지정된 메서드가 호출되는 priority는 Dispatcher 이벤트큐의 다른 보류 중인 조작에 상대적입니다.
method
유형:
System.Delegate
인수를 사용하지 않는 메서드에 대한 위임자로 디스패처 이벤트 큐에 푸시됩니다.
반환값
유형:
System.Object
호출 중인 대리인의 반환 값 또는 대리인에 반환 값이 없는 경우 null입니다.
버전 정보
이후 사용 가능.NET Framework 3.0
언급URL : https://stackoverflow.com/questions/11625208/accessing-ui-main-thread-safely-in-wpf
'programing' 카테고리의 다른 글
DataReader를 목록으로 쉽게 변환하려면 어떻게 해야 합니까? (0) | 2023.04.19 |
---|---|
SQL Server 데이터베이스 버전 제어 방법 (0) | 2023.04.19 |
배시 템플릿:Bash를 사용하여 템플릿에서 구성 파일을 작성하는 방법 (0) | 2023.04.19 |
Bash 스크립트가 병렬로 제한된 수의 명령을 처리합니다. (0) | 2023.04.19 |
+ 또는 -로 시작하는 필드에서는 Excel csv 수식 변환을 바이패스합니다. (0) | 2023.04.19 |