Search code examples
c#wpffreezedispatcher

c# wpf dispatcher.beginInvoke freeze


im working on an application which communicates with server.

thread  = new Thread(new ThreadStart(ClientStart));
thread.SetApartmentState(ApartmentState.STA);                
thread.Start();

private void ClientStart()
    {
        tcpClient = new TcpClient(ip,3000);
        stream = tcpClient.GetStream();
        while (true) {                
            stream.Read(...);
            PrintMessage(...);
        .....
        }
}
private void PrintMessage(LogWin w, string msg)
{
  DateTime dt = DateTime.Now;
  w.GetMessageBox().Dispatcher.BeginInvoke(DispatcherPriority.Input,new Action(()=>w.GetMessageBox()
            .AppendText(String.Format("{0:d/M/yyyy HH:mm:ss}", dt) + " : " + msg)));

}

later i need to print result to a messagebox. I know i have to use Dispatcher, because im working in another thread, but my application freezes even if i use beginInvoke method.

Edit based on Sheridan's answer:

now im getting: An unhandled exception of type 'System.InvalidOperationException' occurred in WindowsBase.dll

Additional information: The calling thread cannot access this object because a different thread owns it.

Dispatcher dispatcher = Dispatcher.CurrentDispatcher;
thread = new Thread(() => ClientStart(dispatcher));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();

private void ClientStart(Dispatcher dispatcher)
    { 
....

and changed print method:

 dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() =>
       w.GetMessageBox()
            .AppendText(String.Format("{0:d/M/yyyy HH:mm:ss}", dt) + " : " + msg)));

solved by using Application.Current.Dispatcher


Solution

  • Always be wary of Dispatcher.CurrentDispatcher as that will will return an object for dispatching on the CURRENT thread - which may not be the UI. You want (and generally almost always want) the UI thread dispatcher.

    You can get that through Application.Current.Dispatcher Which always returns the UI thread dispatcher.

    Its frustating that these calls looks so similar...

    [If you are in the main window you can just call Dispatcher but that probably not the case for you]