0

(免责声明:我是 C# 的新手,只是想弄清楚)

从多个线程与 UI 交互时是否有“最佳实践”?我已经看到一些人建议Invoke每个数据加载器,但其他人建议数据收集线程应该以某种方式通知 UI 线程,并依靠该线程来适当地更新 UI。我更喜欢后者,所以在绘图线程中有一个共享的对象列表和一个循环来显示和删除此列表中的任何内容会更好吗?或者我喜欢的另一个想法是拥有包含控件(或顶级窗口)的方法,例如NotifyDoneGatheringUserList(List<string> namesand NotifyDoneGatheringUserData(User user),因此收集线程不需要知道任何关于共享对象的想法;如果这是可行的,是否有一种System.Window.GetMainWindow()功能风格,或者每次我生成一个收集器时我是否需要/想要传入对象new Thread(GetUserDataFromUser(user, this))

为了显示:

调用

public MainWindow()
{
  new Thread(GetUsers());

public void GetUsers()
{
  List<string> users;
  <load users here>
  mainWindow.Invoke((delegate){userList.Text = users.ToString()});
}

共享对象

public MainWindow()
{
  new Thread(GetUsers());
  // somehow start a look to handle UI updates here without blocking...have to investigate.
}

private Loop() 
{
  while (true)
  {
      lock(sharedList);
      if (!sharedList.empty())
      {
          userList.Text += sharedList.Front().ToString();
          sharedList.PopFront();
      }
      sharedList.Unlock();
      Sleep(50);
  }
}


// data gathering class

public void GetUsers()
{
  List<string> users;
  <load users here>
  lock(mainWindow.sharedList);
  mainWindow.sharedList.Push(users)
  unlock(mainWindow.sharedList);
}

暴露的方法

public MainWindow()
{
  new Thread(GetUsers());
  // somehow start a look to handle UI updates here without blocking...have to investigate.
}

private Loop()
{
  while (true)
  {
      lock(sharedList);
      if (!sharedList.empty())
      {
          userList.Text += sharedList.Front().ToString();
          sharedList.PopFront();
      }
      sharedList.Unlock();
      Sleep(50);
  }
}

public void NotifyUsersLoaded(List<string> users)
{
  lock(this.sharedList);
  this.sharedList.Push(users)
  unlock(thissharedList);
}


// data gathering class

public void GetUsers()
{
  List<string> users;
  <load users here>
  mainWindow.NotifyUsersLoaded(users)
}
4

1 回答 1

0

在我个人看来,这一切都比这简单得多。您认为(通常)我们使用 UI 线程更新 UI 是正确的。至于获取数据和实现长时间运行的功能,我们真的不需要不断地创建新线程,尤其是new Thread()……Thread现在在 .NET 中直接使用类有点“过时”。

delegate将 asynchronous与回调处理程序一起使用要容易得多,或者如果您使用的是 .NET 4.5,则使用出色的 newawait关键字会更容易。如果您不了解这些,请查看以下链接:

使用委托的异步编程

使用 Async 和 Await 进行异步编程(C# 和 Visual Basic)

使用这些方法时,您不需要在工作完成时“通知” UI 线程......要么你有一个回调处理程序delegate,要么你的方法在await关键字之后继续......很好很容易。

编写异步 WPF 应用程序时要注意的最后一件事是,在 UI 中,您可能希望在数据绑定控件上设置类的IsAsync属性...基本上,这只是避免在获取数据时阻塞 UI。BindingTrue

于 2013-09-12T08:20:36.257 回答