我应该如何为应用程序设计类结构,以便异步更新UI

时间:2013-09-12 00:48:03

标签: c# wpf

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

与多个线程的UI交互时是否存在“最佳实践”?我看到有些人建议每个数据加载器使用Invoke,但是其他人建议数据收集线程应该以某种方式通知UI线程,并依赖该线程来适当地更新UI。我更喜欢后者,那么在绘图线程中有一个共享的对象列表和一个循环可以更好地显示和删除此列表中的任何内容吗?或者我喜欢的另一个想法是拥有包含控件(或顶级窗口)的方法,例如NotifyDoneGatheringUserList(List<string> namesNotifyDoneGatheringUserData(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)
}

1 个答案:

答案 0 :(得分:0)

在我个人看来,这比这简单得多。你认为(通常)我们使用UI线程更新UI是正确的。至于获取数据和实现长时间运行的功能,我们实际上并不需要不断创建新线程,尤其不是new Thread() ...直接使用Thread类有点'老式'现在在.NET。

使用带回叫处理程序的异步delegate要容易得多,或者如果您使用的是.NET 4.5,使用优秀的新await关键字会更容易。如果您不了解这些,请查看以下链接:

Asynchronous Programming Using Delegates

Asynchronous Programming with Async and Await (C# and Visual Basic)

使用这些方法时,您无需在工作完成时“通知”UI线程...您有delegate的回叫处理程序,或者您的方法在{ {1}}关键字...简单易用。

编写异步WPF应用程序时最后要注意的是,在UI中,可能想要将await类的IsAsync属性设置为{{1在数据绑定控件上...基本上,这只是避免在获取数据时阻止UI。