2011-10-20 2 views
16

채팅 클라이언트를 구축 중이며 dispatcher 사용 방법에 100 % 확신하지 못했습니다.C# Dispatcher 사용

public void LostConnection() 
{ 
    myGUI.chatBox.AppendText("Lost connection to room: "+ myGUI.UsernameText.ToString() + "\r\n"); 
} 

내가이 Dispatcher.Invoke(myGUI.chatBox...) 내에서 문을 surrond해야합니까 : 그래서 질문은 내가 다음과 같은 방법이있다? 어떤 도움을 주셔서 감사합니다. (내 머리 위로 떨어져)이 같은

+0

그 의존 ... 그 스레드는 어떤 스레드에서 실행됩니까? 또한, WPF를 사용하고 있는지 확인하십시오. ('Dispatcher'는 그걸로 만 작동합니다.) – svick

+1

어떤 UI 프레임 워크를 사용하고 있습니까?(WinForms, WPF 또는 SL) 그들 사이에 차이가 있습니다 –

+0

그래, svick이 제안하는 것처럼 다른 스레드 (비동기 적으로)에서 UI를 건드리는 경우에 따라 달라집니다 – gideon

답변

68

앱은 메인 UI 스레드 (일반적으로 ManagedThreadId==1)가 있습니다. 일반적으로 채팅 앱에서 이벤트는 다른 스레드 (전용 소켓 수신 스레드 또는 수신 코드의 스레드 풀 스레드)에서 제공됩니다. 다른 스레드에서 끌어 당기는 이벤트에서 UI를 업데이트하려면 디스패처를 사용해야합니다. 여기서 유용한 테스트는 코드가 UI 스레드에 있으면 true를 반환하고 다른 스레드에서는 false를 반환하는 Dispatcher.CheckAccess() 메서드입니다. 메인 창에 있다면

using System.Windows.Threading; // For Dispatcher. 

if (Application.Current.Dispatcher.CheckAccess()) { 
    network_links.Add(new NetworkLinkVM(link, start_node, end_node)); 
} 
else { 
    Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(()=>{ 
     network_links.Add(new NetworkLinkVM(link, start_node, end_node)); 
    })); 
} 

당신이 사용할 수 있습니다 :

Dispatcher.BeginInvoke(... 

당신이 someother 상황에서 경우는 뷰 모델을 예 다음 사용 : 일반적인 호출은 뭔가 보이는

Application.Current.Dispatcher.BeginInvoke( 

당신이 원하는 경우에 호출 BeginInvoke 대
사용 Invoke 현재의 thread가 대기하는 UI 스레드까지 UI 스레드에서 작업이 완료 될 때까지 기다리지 않고 현재 스레드를 계속 진행하려는 경우 디스패치 코드 또는 BeginInvoke을 처리했습니다.

메시지 박스, Dispatcher 및 호출/BeginInvoke : 메시지 박스를 해제 할 때까지
Dispatcher.Invoke가 스레드를 차단합니다.
Dispatcher.BeginInvoke은 UI 스레드가 MessageBox 호출을 닫을 때까지 차단하는 동안 스레드 코드가 계속 실행되도록합니다.

CurrentDispatcher 대 Current.Dispatcher!
Dispatcher.CurrentDispatcher은 현재 UI 스레드가 아닌 현재 스레드에 대한 Dispatcher를 리턴한다는 것을 이해합니다. 일반적으로 UI 스레드의 디스패처에 관심이 있습니까? Application.Current.Dispatcher 항상이 값을 반환합니다.

추가 참고 :
당신은 당신의 checkAccess은 종종 다음 유용한 도우미 메서드는 디스패처를 확인하는 데 찾는 경우

public void DispatchIfNecessary(Action action) { 
    if (!Dispatcher.CheckAccess()) 
     Dispatcher.Invoke(action); 
    else 
     action.Invoke(); 
} 

호출 할 수있는 등 :

DispatchIfNecessary(() => { 
    network_links.Add(new NetworkLinkVM(link, start_node, end_node)); 
}); 
+0

안녕 얘들 아, 미안하지만, 지정되지 않았다 네 그것은 wpf 응용 프로그램이며 네 그것은 크로스 스레드입니다. 백엔드에서 위임자를 설정하고 내 모델에 경고 한 다음 디스패처 메소드를 호출하고 GUI 인터페이스를 업데이트합니다. 디스패처를 추가하기 위해 인텔리 센스 옵션을 아직 얻지는 못하고 있지만 강제로 실행하고 실행되는지 확인하려고합니다. 고마워요! 다른 팁? – Tombo890

+0

using 문을 포함하고 Application.Current.Dispatcher를 사용하면 결과를 얻어야합니다. "백엔드"가 dll에 있으면 UI 스레드 Dispatcher를 객체에 전달하여 참조 할 수 있도록해야합니다. – Ricibob

+0

@Ricibob, 그냥 nitpicky 될, 나는 UI 스레드가 항상 1의 ID를 가지고 있다고 생각하지 않습니다. – svick

2

뭔가 작업을해야합니다 :

public void LostConnection() 
{ 
    myGUI.Invoke 
     ((MethodInvoker)delegate 
    { 
     myGUI.chatBox.AppendText("Lost connection to room: "+ myGUI.UsernameText.ToString() + "\r\n"); 
    }); 
} 
+0

WinForms에있을 것입니다. 이 질문은 분명히 WPF에 관한 것입니다. – svick

+1

예. 그 질문에서 분명하지 않았습니다. –

관련 문제