«Неправильно» / Плохой дизайн, чтобы поместить работника темы / фона в класс?

15

У меня есть класс, который будет читать из Excel (C # и .Net 4), и в этом классе у меня есть фоновый работник, который будет загружать данные из Excel, в то время как пользовательский интерфейс может оставаться отзывчивым. У меня такой вопрос: плохо ли иметь фонового работника в классе? Должен ли я создать свой класс без него и использовать фоновый рабочий для работы с этим классом? Я не вижу никаких проблем с созданием своего класса таким образом, но опять же, я новичок, поэтому я решил, что обязательно позабочусь, прежде чем продолжить.

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

Jetti
источник
3
почему вы думаете, что это может быть неправильно?
Alb
1
@Alb - сложно сказать. Мой код работает и удовлетворяет мои потребности, однако я планирую использовать это в проекте, который я сделаю с открытым исходным кодом. Я хочу убедиться, что мой код не «просто работает» и действительно хорошо спроектирован.
Джетти

Ответы:

21

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

Да, ты должен. И я скажу вам, почему - вы нарушаете принцип единой ответственности . Тесно связывая класс, который обращается к документу Excel, с тем, как он обращается к документу Excel, вы исключаете возможность для кода «контроллера» (любого кода, который его использует) делать это по-другому. Вы можете спросить, насколько они разные? Что если в коде контроллера есть две операции, которые занимают много времени, но хотят, чтобы они были последовательными? Если вы позволили контроллеру обрабатывать потоки, он может одновременно выполнять обе длительные задачи в одном потоке. Что, если вы хотите получить доступ к документу Excel из контекста, не связанного с пользовательским интерфейсом, и не нуждаетесь в нити?

Перекладывая ответственность за многопоточность на вызывающую сторону, вы обеспечиваете большую гибкость кода, делая его более пригодным для повторного использования.

Ней
источник
2
+1 за ответ на заданный вопрос и за хороший ответ.
Адам Лир
+1 - Спасибо, Неми. Вы ответили на мой вопрос на месте, я ценю это. Я вытащу это из своего класса и переведу в новый класс, еще раз спасибо!
Джетти
@Nemi - было бы приемлемо, если бы я создал другой метод, который бы имел синхронную загрузку и затем имел бы асинхронный метод? Или было бы лучше иметь один метод синхронной загрузки, а затем перейти оттуда?
Джетти
1
У меня лично не было бы метода синхронизации и метода асинхронности. Вы все еще выполняете обязанности. Я работал с этой проблемой много раз. То, что я сделал, было создано TaskController, который был смоделирован после SwingWorker, но имел специальный код для нашего приложения. TaskController выполнял такие вещи, как обновление индикатора выполнения, изменение курсора мыши и т. Д. Может показаться, что код панели задач всегда должен создавать TaskController для выполнения вызовов, но в конечном итоге код становится более надежным и более обслуживаемым.
Неми
Спасибо, Неми! Хотел бы я снова проголосовать за тебя, потому что ты определенно ответил на мой вопрос и указал мне правильное направление. Еще раз спасибо !!
Джетти
3

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

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

стихарь
источник
1
Несмотря на то, что я правильно прочитал его вопрос, у него нет проблем с пониманием этого вопроса.
Неми
Извините, если мой вопрос был неверно истолкован. Я знаю, что разделение пользовательского интерфейса и фоновых задач - хороший дизайн (если нет необходимости, мой тестовый файл Excel занимает более 8 тыс. Строк и может показаться, что программа не отвечает). Мой вопрос заключается в том, хорошо ли тесно связать нить с классом Excel.
Джетти
0

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

Райан Микела
источник
Просто чтобы прояснить, мой класс не касается пользовательского интерфейса. У него есть два события, которые позволят любому, кто его использует, обновить интерфейс в случае необходимости, но мой класс сам по себе не касается интерфейса.
Джетти
0

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

Также, если вы выполняете итерацию, которая не требует обработки элементов в определенном порядке, рассмотрите возможность использования ThreadPool вместо этого (или если вы используете .NET 4, используйте библиотеку параллельных задач ).

Майкл Браун
источник
Спасибо за ваш ответ. Я создал два события в своем классе, которые будут инициировать прогресс (в основном, оборачивая событие прогресса BackgroundWorker, поскольку BackgroundWorker является частным), который отправляет прогресс в пользовательский интерфейс (индикатор выполнения).
Джетти