События и многопоточный код в .NET

Проект - C #.

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

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

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

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


person Joel Barsotti    schedule 22.12.2009    source источник


Ответы (3)


Судя по тому, что вы описываете, лучшим вариантом может быть присвоение всем вашим объектам SynchronizationContext в качестве аргумента в их конструкторе.

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

Таким образом, ваша библиотека не зависит от пользовательского интерфейса (может работать в Windows Forms или WPF), и вы можете вызывать события в потоке пользовательского интерфейса по мере необходимости.

Пользователь вашей библиотеки просто создаст ваш объект, используя SynchronizationContext. Текущий (который дает вам допустимый контекст в приложениях Windows Forms и WPF, без ссылки на них).

person Reed Copsey    schedule 22.12.2009
comment
Да, вот и все, способ формирования сообщения Post немного сложен, но он будет идеальным. - person Joel Barsotti; 22.12.2009
comment
Я, вероятно, перенесу это в отдельный поток, но я видел пример, в котором метод, вызывающий событие, сравнивает текущий контекст SyncrhonizationContext с тем, который я сохраняю из пользовательского интерфейса. В WPF это никогда не кажется правдой. Итак, я получаю бесконечную рекурсию, и пользовательский интерфейс блокируется. Знаете ли вы хорошую независимую проверку пользовательского интерфейса, чтобы узнать, нужно ли мне делать публикацию? Должен ли я просто всегда звонить по почте и просто публиковать событие напрямую? - person Joel Barsotti; 23.12.2009
comment
Что ж, вы всегда можете опубликовать / отправить и не беспокоиться об этом. Это будет иметь (небольшие) накладные расходы, если в них нет необходимости, но обычно это не проблема. Если вы на самом деле находитесь в фоновом потоке, SynchronizationContext.Current будет иметь значение null (поскольку у обычных потоков нет прикрепленного контекста). - person Reed Copsey; 23.12.2009
comment
да, я это заметил. Но после SyncrhonizationContext.Post в Windows Forms SyncrhonizationContext.Current будет оценивать по оператору == значение, которое я храню в своем синглтоне, в WPF этого не будет. Я просто использую неправильное значение для проверки, или если я просто проверяю SyncrhonizationContext.Current на нулевое условие, может ли эта более легкая проверка вернуться, чтобы укусить меня? Кроме того, если сообщение довольно легкое, то, возможно, просто всегда отправлять и терять рекурсию - правильный ответ. Большое вам спасибо за вашу помощь. - person Joel Barsotti; 23.12.2009

Используя таймер или отвечая на событие, поток пользовательского интерфейса (или объект привязки к данным в потоке) может опросить объект «статуса» и ограничить объем работы, которую должен выполнить пользовательский интерфейс.

person Doug L.    schedule 22.12.2009

Вы смотрели фасад, Прокси, Factory и шаблоны Singleton?

Если вы реализуете свой основной объект как синглтон и предоставляете прокси и фабричные методы для создания и доставки их вызывающим объектам вашей библиотеки, это становится довольно простым. Паттерн Фасад может упростить эту задачу, абстрагируя большую часть внутренней части того, что происходит в серверной части.

Комбинация Factory и Singleton и обеспечение того, чтобы все классы, которые вы хотите открыть, имели конструкторы, требующие вашего основного объекта, - хороший способ реализовать этот дизайн. Я не знаю основных требований / дизайна вашей библиотеки, поэтому не уверен, сработает это для вас или нет.

person GrayWizardx    schedule 22.12.2009
comment
Да, это на самом деле что-то вроде этого. Я думаю, что в сочетании с SynchronizationContext у меня должно быть то, что мне нужно, чтобы делать то, что я хочу. - person Joel Barsotti; 22.12.2009