#c# #.net #winforms #multithreading #user-interface
#c# #.net #winforms #многопоточность #пользовательский интерфейс
Вопрос:
Вот моя цель: приложение состоит из формы — MainForm — которая содержит множество вкладок (похожих на графический интерфейс Notepad ). Каждая вкладка является дочерним элементом UserControl (UCDx). MainForm может отображать 2 или более вкладок, которые содержат экземпляры одного и того же UCDx. Цель состоит в том, чтобы UCDx должен был выполнять некоторые трудоемкие действия или выполнение методов, то есть чтение / запись в БД, вызовы методов веб-службы. Такого рода действия я бы хотел выполнять в отдельных потоках, чтобы не замораживать пользовательский интерфейс. Также мне нужно будет реализовать информационную форму (InfoForm), которая будет отображать информацию о текущих запущенных потоках с некоторой функциональностью взаимодействия, то есть закрывать потоки, которые выполняются слишком долго.
Основными проблемами, с которыми я столкнулся, являются:
- взаимодействие потока с графическим интерфейсом — т. Е. Поток считывает данные, которые должны отображаться в таблице;
- управление взаимодействием потоков — после внедрения InfoForm.
В совместном / параллельном программировании я новичок — может кто-нибудь дать некоторые подсказки о том, как это реализовать?
Ответ №1:
Я бы сначала отделил вашу рабочую логику от пользовательского интерфейса.
Например, для «потока, которому необходимо считывать данные и отображать их», попробуйте разделить вашу проблему на более мелкие части:
-
Создайте простой класс, который имеет метод синхронной обработки, без использования потоков. Что-то вроде:
interface IServiceReader { Data GetDataFromService(IServiceInfo info); }
-
Протестируйте это. Создайте модульные тесты или даже небольшое консольное приложение, где вы увидите, что оно отлично работает без графического интерфейса.
-
Создайте класс асинхронной оболочки, который вызывает
ServiceReader
для выполнения задания, но вызывает его в фоновом потоке и запускает событие по завершении.interface IAsyncServiceReader { void Start(IServiceInfo info); event EventHandler<Data> DataReceived; }
-
Снова протестируйте это. Это должна быть отдельная библиотека классов, независимая от вашего графического интерфейса.
-
Используйте MVC или аналогичный шаблон, чтобы отделить ваши представления (вкладки) от вашей модели (async service reader). Это означает, что вы должны запускать события взаимодействия из своих представлений, обрабатывать их в контроллере, а затем позволять контроллеру вызывать соответствующее действие в модели:
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); } }
-
Наконец, убедитесь, что вызовы фонового потока отправляются в нужный поток (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, и это сохранит вашу бизнес-логику нетронутой.
Ответ №2:
Используйте вызов из фоновых потоков для выполнения действий в графическом интерфейсе. Существует множество решений для многопоточности: задачи, фоновые рабочие, пользовательские потоки, пул потоков. Вы также можете использовать асинхронные операции.
Ответ №3:
хорошо, ребята … после прочтения большого количества информации по этой проблеме (наиболее важные документы Albahari threads) — вот первая попытка реализации моих мыслей — возьмите через svn из gCode. Пожалуйста, прокомментируйте как можно больше, ребята — мне нужны наши мнения и наблюдения. Спасибо.