【问题标题】:C# .NET 5.0 Wpf UI modified by another threadC# .NET 5.0 Wpf UI 被另一个线程修改
【发布时间】:2021-04-06 18:31:35
【问题描述】:

我在从另一个线程更新 WPF UI 时遇到了一些麻烦。 第二个线程是一个不断从StreamReader 读取消息的循环。 在这些消息中有更新UI 的命令。

我不知道该怎么做。我读过关于类似问题的文章,但不一样

WPF 界面:

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

其他话题:

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)
    {
    }
  }
}

【问题讨论】:

标签: c# wpf multithreading .net-5


【解决方案1】:

当您已经进行异步调用时不要创建线程。

只需在异步事件处理程序中调用并等待异步方法。因此,UI 更新将在 UI 线程中进行。不需要 Dispatcher 调用。

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

除此之外,您显然还需要一些机制来停止订阅方法中的无限循环。

【讨论】:

    【解决方案2】:

    您需要使用BeginInvoke 方法。类似的东西:

      .....
        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            
    .....
    

    另外,作为旁注,不要每个人都接受例外。记录或/和处理 catch 块上的异常

    【讨论】:

    • 这不起作用。 var dispatcher = Application.Current.MainWindow.Dispatcher; 我创建了一个名为“window”的 MainForm 实例,window.Dispatcher.BeginInvoke(new Action(window.test)); 我找不到将参数传递给“test”方法的方法,所以我创建了一个 STATIC 对象并在调用该方法之前对其进行评估。对吗?
    【解决方案3】:

    您必须调用调度程序才能更新 UI

    Dispatcher.BeginInvoke(() =>
             {
                 //Update the UI
             });
    

    【讨论】:

      猜你喜欢
      • 2020-10-15
      • 2014-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多