【问题标题】:Managing threads in an .NET WinForm application在 .NET WinForm 应用程序中管理线程
【发布时间】:2011-12-11 16:08:56
【问题描述】:

这是我的目标:该应用程序包含一个表单 - MainForm - 其中包含许多选项卡(类似于 Notepad++ GUI)。每个选项卡都是一个 UserControl 后代 (UCDx)。 MainForm 可以显示 2 个或更多包含相同 UCDx 实例的选项卡。目标是 UCDx 必须执行一些耗时的操作或方法执行 - 即 DB 读/写、Web 服务方法调用。这种操作我想在单独的线程中运行,以免冻结 UI。我还需要实现一个信息表单 (InfoForm) - 它将显示当前正在运行的线程的信息,并具有一些交互功能 - 即关闭运行时间过长的线程。

我遇到的主要问题是:

  • 线程与 GUI 交互 - 即线程读取应显示在网格中的数据;
  • 线程交互管理 - 在实现 InfoForm 时。

在并发/并行编程中,我是初学者 - 有人可以提供一些关于如何实现它的线索吗?

【问题讨论】:

    标签: c# .net winforms multithreading user-interface


    【解决方案1】:

    好的,伙计们...在阅读了有关此问题的大量信息(最重要的Albahari threads docs)之后-这是实现我的想法的第一次尝试-从gCode获取通过svn。 请尽可能多地发表评论-我需要我们的意见和观察。谢谢。

    【讨论】:

      【解决方案2】:

      我会首先将您的工作逻辑与 UI 分开。

      例如,对于“需要读取数据并显示它的线程”,尝试将您的问题分成更小的部分:

      1. 创建一个具有同步处理方法的普通类,不涉及线程。比如:

        interface IServiceReader
        {
             Data GetDataFromService(IServiceInfo info);
        }
        
      2. 测试一下。创建单元测试,甚至是一个小型控制台应用程序,您可以在其中看到它在没有 GUI 的情况下也能正常工作。

      3. 创建一个异步包装类,它调用ServiceReader 来完成这项工作,但在后台线程上调用它,并在完成时触发一个事件。

        interface IAsyncServiceReader
        {
             void Start(IServiceInfo info);
             event EventHandler<Data> DataReceived;
        }
        
      4. 再次进行测试。这应该是一个独立的类库,独立于您的 GUI。

      5. 使用 MVC 或类似模式将视图(选项卡)与模型(异步服务阅读器)分开。这意味着您应该从视图中触发交互事件,在控制器中处理它们,然后让控制器在模型中调用适当的操作:

        class Controller
        {
             readonly ITabView _view; 
             readonly IAsyncServiceReader _model;
             public Controller(ITabView view, IAsyncServiceReader model)
             {
                  _view = view; _model = model;
                  AttachHandlers();
             }
        
             void AttachHandlers()
             {
                  view.UserRequestedLoading += (sender,info) => model.Start(info);
                  model.DataReceived += (sender,data) => view.DisplayData(data);
             }
        }
        
      6. 最后,确保后台线程调用被分派到正确的 (GUI) 线程。这只是意味着您的选项卡视图需要检查是否需要调用:

        class TabView : UserControl
        {
             void DisplayData(Data data)
             {
                 if (this.InvokeRequired)
                 {
                     BeginInvoke(new Action<Data>(DisplayData), data);
                     return;
                 }
        
                 // otherwise, display the data in some way
                 dataGrid.DataSource = data; ...
             }
        }
        

      将模型与视图分离将简化测试以及以后对 UI 的更改。您可以决定将其作为控制台应用程序或 Windows 服务,这将保持您的业务逻辑完整。

      【讨论】:

        【解决方案3】:

        使用从后台线程调用来在 GUI 上执行操作。多线程有很多解决方案:任务、后台工作者、自定义线程、线程池。你也可以使用异步操作。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-10-10
          • 1970-01-01
          • 2023-03-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-21
          相关资源
          最近更新 更多