0

I'm having some trouble in updating a WPF UI from another Thread. The second Thread is a loop that constantly read messages from a StreamReader. In these messages there are commands that update the UI.

I have no idea how to do. I read articles about similar problems but were not the same

WPF interface:

private void Button_Click(object sender, RoutedEventArgs e)
{
   Thread threadConsume = new Thread(pre_sub);
   threadConsume.Start();
}

Other thread:

private void pre_sub()
{
    Subscribe();
}
public async Task Subscribe()
{
  while (true)
  {
    try
    {
       Console.WriteLine("Establishing connection");
       using (var streamReader = new StreamReader(await _client.GetStreamAsync(_urlSubscription)))
       {
          while (!streamReader.EndOfStream)
          {
              var stream = await streamReader.ReadLineAsync();
              if (stream.ToString() == "update")
              {
                  //update the WPF UI
              }
          }
       }
    }
    catch (Exception ex)
    {
    }
  }
}
Beso
  • 1,176
  • 5
  • 12
  • 26
Vez
  • 55
  • 8

3 Answers3

4

Do not create a Thread when you already make async calls.

Simply call and await the async method in an async event handler. The UI updates would thus be made in the UI thread. No Dispatcher calls would be necessary.

private async void Button_Click(object sender, RoutedEventArgs e)
{
    await Subscribe();
}

Besides that, you would obviously need some mechanism that stops the infinite loop in the Subscribe method.

Clemens
  • 123,504
  • 12
  • 155
  • 268
1

You need to use BeginInvoke method. Something in the line of:

  .....
    while (!streamReader.EndOfStream)
          {
                  var stream = await streamReader.ReadLineAsync();
                  if (stream.ToString() == "update")
                  {                          
                   var dispatcher = Application.Current.MainWindow.Dispatcher;
                   dispatcher.BeginInvoke(new Action(() =>
                   {
                     //update the WPF UI
                   }), (DispatcherPriority)10);
                  }
          }
   break; ///if UI Updated exit the while true loop            
.....

Also, as a side note, don't every swallow exceptions. Log or/and handle the exception on catch block

apomene
  • 14,282
  • 9
  • 46
  • 72
  • This doesn't work. `var dispatcher = Application.Current.MainWindow.Dispatcher;` I created an instance of the MainForm called "window" and `window.Dispatcher.BeginInvoke(new Action(window.test));` I can't find a way to pass parameters to the Method "test" so I create a STATIC object and valorise it before calling the method. Is correct ? – Vez Dec 30 '20 at 13:34
0

You have to call dispatcher in order to update the UI

Dispatcher.BeginInvoke(() =>
         {
             //Update the UI
         });
pantelis
  • 170
  • 1
  • 6