在.net WinForm应用程序中管理线程

本文关键字:管理 线程 应用程序 net WinForm | 更新日期: 2023-09-27 18:11:42

这是我的目标:应用程序由一个表单- MainForm -其中包含许多选项卡(类似于notepad++ gui)。每个选项卡都是UserControl的后代(UCDx)。MainForm可以显示2个或更多包含相同UCDx实例的选项卡。目标是UCDx将不得不执行一些耗时的操作或方法执行——例如DB读/写,Web服务方法调用。为了不冻结UI,我希望在单独的线程中运行这类操作。此外,我需要实现一个信息表单(InfoForm) -这将显示当前运行的线程信息,与一些交互功能-即关闭线程运行太长。

我面临的主要问题是:

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

在并发/并行编程我是初学者-谁能给一些线索,如何实现?

在.net WinForm应用程序中管理线程

我首先会把你的worker逻辑从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服务,这将保持你的业务逻辑完整。

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

好了,伙计们…在阅读了很多关于这个问题的信息(最重要的Albahari线程文档)-这是第一次尝试实现我的想法-通过svn从gCode。请尽可能多地评论,我需要我们的意见和观察。谢谢你。