.NET: Механизм для синхронизации продолжительных задач

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

  1. Отправьте некоторую информацию о прогрессе о задаче (прогресс, действие, регистрирующееся и т.д.)
  2. Имейте способ прервать задачу перед завершением, если некоторый внешний сигнал или свойство были установлены.

Я реализовал платформу для этого, но это требует, чтобы все такие задачи сослались на блок, который содержит эту платформу.

Мой вопрос: существует ли уже встроенный механизм в платформе.NET (3.5 или ниже) для проблемы, описанной выше?

Я знаю, что мог использовать события, но это будет означать, что длительные задачи должны были бы выставить такие события, которые я думаю, издержки. Идеально я хочу иметь платформу, которая скрывает проблемы многопоточности и является дружественным внедрением зависимости, но не зависела бы от дополнительного пользовательского блока и не загрязнит исходный интерфейс.

Я надеюсь, что описал проблему достаточно хорошо. В противном случае я могу отправить некоторые образцы интерфейсов от моей собственной платформы.

ОБНОВЛЕНИЕ: хорошо, я думаю, что для моего описания проблемы нужно немного разъяснения :). Когда я говорю "продолжительный", я не имею в виду "долго" в смысле рабочего процесса. Я работаю над WinForms, отображающим приложение, которое делает все виды материала, как генерация вспомогательных контуров. Чтобы сделать это, это сначала должно загрузить файлы данных повышения с FTP-сервера, разархивировать их и затем выполнить некоторые вычисления. Я написал код для этого давным-давно, но для создания его более благоприятным для GUI, я должен модифицировать различные проверки - например, обнаружив, что пользователь нажал на кнопку Abort и останавливает процесс.

Таким образом, в основном мое беспокойство: как написать код, который может позже (если когда-либо) использоваться в среде GUI, куда Вы не можете просто работать, все в основном GUI распараллеливает и замораживает целое приложение. Проблема состоит в том, чтобы найти способ сделать Ваш код подходящим в целях GUI, не связывая его с конкретной платформой GUI.

7
задан Igor Brejc 20 February 2010 в 15:33
поделиться

4 ответа

Взгляните на образец саги. Он не встроен в структуру, но может быть реализован. В качестве альтернативы и NServiceBus, и MassTransit имеют реализации этого. У Арнона Р.ГО есть черновик из своей книги (будет ли он когда-нибудь закончен), описывающий его здесь .

По моему опыту, работа с NServiceBus намного проще, чем WF, а также более мощная (хотя я не смотрел на WF 4, который по всем описаниям является почти полной переработкой WF, поскольку Microsoft признала недостатки это).

Даже если вам не нужен фреймворк вроде NServiceBus или MassTransit, стоит взглянуть на сам шаблон, поскольку он очень точно соответствует вашему проблемному пространству по сравнению с тем, что вы описали.

2
ответ дан 7 December 2019 в 03:15
поделиться

Это зависит от сложности вашей системы. Для решения относительно простых задач вы, вероятно, могли бы использовать класс BackgroundWorker из .NET 2.0. Он поддерживает отчеты о ходе операции с помощью события OnProgressChanged , а также поддерживает отмену фоновой задачи с помощью метода CancelAsync .

Класс управляется событиями, но, поскольку это уже часть класса, я не думаю, что для вас это накладные расходы:

var bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(RunWorkerCompleted);
bw.ProgressChanged += new ProgressChangedEventHandler(ProgressChanged);
  • Метод DoWork выполняется для запуска в фоновом режиме задача (он может сообщить о ходе выполнения, вызвав bw.ReportProgress , и проверить ожидающую отмену с помощью bw.CancellationPending ).

  • Метод RunWorkerCompleted выполняется в потоке графического интерфейса после завершения операции (что дает удобный способ синхронизации, не беспокоясь о параллелизме).

  • Запускается событие ProgressChanged всякий раз, когда ваш метод DoWork сообщает об изменении хода выполнения.

Я считаю, что для более простых задач вы можете представлять свои задачи как фоновые рабочие.

1
ответ дан 7 December 2019 в 03:15
поделиться

Это звучит очень похоже на Windows Workflow Foundation

6
ответ дан 7 December 2019 в 03:15
поделиться

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

0
ответ дан 7 December 2019 в 03:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: