Управление потоками в приложении .NET WinForm - PullRequest
2 голосов
/ 20 октября 2011

Вот моя цель: приложение состоит из формы - MainForm - которая содержит множество вкладок (Notepad ++ GUI-like).Каждая вкладка является потомком UserControl (UCDx).MainForm может отображать 2 или более вкладок, которые содержат экземпляры одного и того же UCDx.Цель состоит в том, чтобы UCDx пришлось выполнять некоторые трудоемкие действия или выполнять методы - например, чтение / запись в БД, вызовы методов веб-службы.Такого рода действия я бы хотел выполнять в отдельных потоках, чтобы не заморозить интерфейс.Также мне нужно будет реализовать информационную форму (InfoForm), которая будет отображать информацию о текущих запущенных потоках, с некоторыми функциями взаимодействия, то есть закрывать потоки, которые выполняются слишком долго.

Основные проблемы, с которыми я столкнулся:

  • взаимодействие потока с GUI - то есть поток читает данные, которые должны отображаться в сетке;
  • управление взаимодействием потока - при реализации InfoForm.

Вя начинающий - кто-то может подсказать, как это реализовать?

Ответы [ 3 ]

4 голосов
/ 20 октября 2011

Сначала я бы отделил вашу рабочую логику от пользовательского интерфейса.

Например, для «потока, который должен прочитать данные и отобразить их», попробуйте разбить вашу проблему на более мелкие части:

  1. Создайте простой класс, который имеет метод синхронной обработки, без использования потоков.Что-то вроде:

    interface IServiceReader
    {
         Data GetDataFromService(IServiceInfo info);
    }
    
  2. Проверьте это.Создайте модульные тесты или даже небольшое консольное приложение, где вы можете видеть, что оно отлично работает без графического интерфейса.

  3. Создайте асинхронный класс-обертку, который вызывает ServiceReader для выполнения работы, но вызывает его в фоновом потоке и запускает событие по завершении.

    interface IAsyncServiceReader
    {
         void Start(IServiceInfo info);
         event EventHandler<Data> DataReceived;
    }
    
  4. Снова протестируйте его.Это должна быть отдельная библиотека классов, независимая от вашего графического интерфейса.

  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; ...
         }
    }
    

Отделение модели от представления упростит тестирование и последующие изменения пользовательского интерфейса.Вы можете решить сделать это консольным приложением или службой Windows, и это сохранит вашу бизнес-логику нетронутой.

0 голосов
/ 26 октября 2011

хорошо, ребята ... после прочтения большого количества информации по этой проблеме (наиболее значимые документы по альбахарским потокам ) - вот первая попытка реализовать мои мысли - взять через svn из gCode . Пожалуйста, прокомментируйте как можно больше, ребята - мне нужны наши мнения и наблюдения. Спасибо.

0 голосов
/ 20 октября 2011

Используйте Invoke из фоновых потоков для выполнения действий в графическом интерфейсе. Существует множество решений для многопоточности: задачи, фоновые рабочие, настраиваемые потоки, пул потоков. Вы также можете использовать асинхронные операции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...