管理.NET WinForm应用程序中的线程

时间:2011-10-20 10:12:17

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

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

我遇到的主要问题是:

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

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

3 个答案:

答案 0 :(得分:4)

我首先将您的工作逻辑与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; ...
         }
    }
    
  7. 将模型与视图分离将简化测试,并稍后更改UI。您可以决定将其设置为控制台应用程序或Windows服务,这将保持您的业务逻辑不变。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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