Dispatcher를 사용하여 WPF 컨트롤을 비메인 스레드에서 변경합니다.호출하다
저는 최근에 WPF에서 프로그래밍을 시작했는데 다음과 같은 문제에 부딪혔습니다.어떻게 사용하는지 모르겠어요.Dispatcher.Invoke()
방법.스레드화 경험이 있으며, 간단한 Windows Forms 프로그램을 몇 개 만들었습니다.
Control.CheckForIllegalCrossThreadCalls = false;
네, 그게 좀 재미없다는 건 알지만 이것들은 단순한 감시 어플리케이션이었습니다.
이 시점에서 백그라운드에서 데이터를 취득하는 WPF 애플리케이션을 작성하고 새로운 스레드를 시작하여 (웹 서버에서) 데이터를 취득하는 콜을 발신하고 WPF 폼에 표시합니다.문제는 이 스레드에서 컨트롤이 안 된다는 거예요.라벨이나 뭐 그런 것도 없어요.이 문제를 어떻게 해결할 수 있을까요?
답변 코멘트:
@Jalfp:
그럼 데이터를 얻을 때 '새로운 디딤판'에 디스패처 방식을 사용하는 건가요?또는 백그라운드워커에게 데이터를 가져와 필드에 삽입하고 이 필드가 채워질 때까지 대기하는 새로운 스레드를 시작하여 디스패처를 호출하여 취득한 데이터를 컨트롤에 표시해야 합니까?
우선 Dispatcher는 긴 차단 작업(WebServer에서 데이터 가져오기 등)을 실행하도록 설계되지 않았습니다.UI 스레드에서 실행되는 작업(예: 진행률 표시줄 값 업데이트)을 실행하려는 경우 디스패처를 사용할 수 있습니다.
백그라운드워커에서 데이터를 취득하여 ReportProgress 메서드를 사용하여 UI 스레드의 변경을 전파할 수 있습니다.
Dispatcher를 직접 사용해야 하는 경우에는 다음과 같이 매우 간단합니다.
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() => this.progressBar.Value = 50));
japf가 정답을 맞췄습니다.만약 당신이 여러 줄의 동작을 보고 있다면 다음과 같이 쓸 수 있습니다.
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() => {
this.progressBar.Value = 50;
}));
성능에 대해 알고 싶은 다른 사용자를 위한 정보:
고성능을 위해 코드를 작성해야 할 경우 CheckAccess 플래그를 사용하여 먼저 호출이 필요한지 여부를 확인할 수 있습니다.
if(Application.Current.Dispatcher.CheckAccess())
{
this.progressBar.Value = 50;
}
else
{
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() => {
this.progressBar.Value = 50;
}));
}
CheckAccess() 메서드는 Visual Studio 2015에서 숨겨져 있으므로 인텔리센스가 이를 표시할 것으로 예상하지 않고 작성하십시오.Check Access에는 퍼포먼스에 대한 오버헤드가 있습니다(몇 나노초만에 오버헤드가 발생합니다).어떤 대가를 치르더라도 호출을 실행하는 데 필요한 마이크로초를 절약하고 싶을 때만 이 방법이 더 좋습니다.또한 호출 메서드가 UI 스레드에 있는지 확인할 때 두 개의 메서드를 만드는 옵션이 항상 있습니다(호출이 있는 경우 및 없는 경우).발송 담당자의 이런 면을 봐야 할 경우는 극히 드문 경우입니다.
스레드가 실행 중일 때 현재 스레드에 의해 차단된 기본 UI 스레드를 실행하려면 다음을 사용하십시오.
현재 스레드:
Dispatcher.CurrentDispatcher.Invoke(MethodName,
new object[] { parameter1, parameter2 }); // if passing 2 parameters to method.
기본 UI 스레드:
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background, new Action(() => MethodName(parameter)));
위의 @japf 답변은 정상적으로 동작하고 있으며, 제 경우 CEF 브라우저가 페이지 로드를 마치면 마우스 커서를 Spining Wheel에서 일반 Arrow로 되돌리고 싶었습니다.누군가에게 도움이 될 수 있는 경우, 코드는 다음과 같습니다.
private void Browser_LoadingStateChanged(object sender, CefSharp.LoadingStateChangedEventArgs e) {
if (!e.IsLoading) {
// set the cursor back to arrow
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background,
new Action(() => Mouse.OverrideCursor = Cursors.Arrow));
}
}
언급URL : https://stackoverflow.com/questions/1644079/change-wpf-controls-from-a-non-main-thread-using-dispatcher-invoke
'programing' 카테고리의 다른 글
어떤 Git 브런치가 어떤 리모트/업스트림 브런치를 추적하고 있는지 어떻게 알 수 있습니까? (0) | 2023.04.09 |
---|---|
Windows에서 구성 파일 /usr/local/ssl/openssl.cnf를 열 수 없습니다. (0) | 2023.04.09 |
CSS에 비례하여 이미지 크기를 조정하시겠습니까? (0) | 2023.04.09 |
왜 스위프트에 편의 키워드가 필요한가? (0) | 2023.04.09 |
StringFormat을 사용한 WPF 바인딩이 ToolTips에서 작동하지 않음 (0) | 2023.04.09 |