Я пишу плагин для другой программы, которая использует нативную программу, чтобы открыть серию файлов для извлечения некоторых данных. Одна проблема, с которой я сталкиваюсь, заключается в том, что процесс занимает много времени, и я хочу, чтобы пользовательский интерфейс не завис Кроме того, я также хочу дать пользователю возможность отменить процесс до его завершения. В прошлом я использовал фоновый рабочий для этого типа вещей, но в этом случае я не думаю, что BackgroundWorker будет работать.
Чтобы создать плагин через API, который я использую, можно создать собственную команду, наследуя интерфейс IAPICommand. Этот интерфейс включает метод Execute (приложение-приложение). Затем создается экземпляр класса, и программа вызывает метод Execute (), когда пользователь вызывает пользовательскую команду в программе.
Методу Execute () передается ссылка на текущий объект приложения, когда он вызывается, и именно этот объект приложения используется для открытия файлов, из которых извлекаются данные. Однако экземпляр приложения не может открыть документ по запросу потока, отличного от исходного потока Execute ().
Таким образом, обычно пользовательский интерфейс существует в основном потоке, а извлечение данных, требующее много времени, выполняется во вторичном потоке. Однако в этом случае извлечение данных должно выполняться в основном потоке, и мне нужно создать дополнительный поток для пользовательского интерфейса.
Вот урезанная версия кода.
class MyCommand:IAPICommand
{
public void Execute(Application app) // method from IAPICommand
{
Thread threadTwo= new Thread(ShowFormMethod);
threadTwo.Start();
}
public void ProcessWidget(Widget w, Application app)
{
//uses an App to work some magic on C
//app must be called from the original thread that called ExecuteCommand()
}
//method to open custom form on a seperatethread
public void ShowFormMethod()
{
MyForm form = new MyForm();
form.ShowDialog();
}
}
Вот блок-схема, которая показывает, как я думаю , что в конечном итоге это должно работать.
альтернативный текст http://dl.dropbox.com/u/113068/SOMLibThreadingDiagram.jpg
- Имеет ли эта диаграмма какой-либо смысл, и если да, то я даже принимаю правильный подход для решения этой проблемы?
- Как только основной поток запускает поток пользовательского интерфейса, я хочу, чтобы он дождался, пока пользователь выберет виджеты для обработки, или завершит команду, закрыв форму (красные цифры на диаграмме). Как я могу заставить основной поток ждать, и как я могу заставить его продолжить либо обработку, либо продолжить до конца, когда поток пользовательского интерфейса заканчивается? Я думал, что мог бы ждать основного потока при блокировке монитора. Затем поток пользовательского интерфейса заполнил бы статический список виджетов, которые должны быть обработаны, и затем отправил бы импульс основному потоку для запуска обработки. Поток пользовательского интерфейса также будет отправлять импульс основному потоку, когда форма закрыта, и основной поток будет знать, продолжать ли выполнение команды до конца, если он когда-либо был обработан, когда список обрабатываемых виджетов пуст.
- Как разрешить основному потоку сообщать о ходе или завершении обработки виджета обратно в поток пользовательского интерфейса (желтые стрелки на диаграмме)? Я просто использовал метод BeginInvoke () формы для этого?
- Как разрешить потоку пользовательского интерфейса отменить обработку виджета (зеленая стрелка на диаграмме)? Я думаю, я мог бы просто установить статический логический флаг, который проверяется перед обработкой каждого виджета?