#c# #winforms #multithreading
#c# #winforms #многопоточность
Вопрос:
Я хочу запустить 2 фоновых потока. Один поток действует как сервер для клиента, а другой поток действует как клиент для сервера. Это приложение является одновременно серверным и клиентским приложением. Должен ли я запускать эти потоки в функции Main () перед вызовом Application.Run()? Или их следует создавать после загрузки основной формы? Я пытаюсь отделить пользовательский интерфейс и бизнес-логику друг от друга, но я знаю, что этим потокам нужно будет уведомлять о событиях в форме. Какова наилучшая практика кодирования для этого? Спасибо!
Ответ №1:
Если им необходимо выполнить логику в основной форме, вам понадобится эта логика для запуска в потоке, в котором была создана основная форма. Таким образом, и клиенту, и серверу необходимо будет иметь ссылку на основную форму, чтобы они могли вызывать для нее либо Invoke, либо BeginInvoke (в зависимости от того, должен ли код в основной форме быть синхронным или асинхронным). Поэтому вам, вероятно, следует запускать потоки после загрузки основной формы, чтобы вы могли передать ссылку на нее клиенту и серверу.
Комментарии:
1. Значит ли это, что мне нужно передавать ссылку на основную форму по всем классам бизнес-логики?
2. Только в тех местах, где вам может потребоваться вызвать код в основной форме. Я предполагаю, что альтернативным подходом было бы предоставить вашу основную форму некоторому глобальному классу, на который ссылается вся ваша бизнес-логика, или статическому классу. В этом случае вы могли бы создавать потоки в
Main()
методе. Вам просто нужно было бы убедиться, что любое свойство или метод, предоставляющий доступ к основной форме, не возвращает null, прежде чем вызывать в ней какой-либо код. Кроме того, вы всегда должны проверять, не удалена ли форма, прежде чем вызывать в ней код.3. Как бы мне настроить глобальный класс, содержащий основную форму?
4. Это зависит от того, как настроено ваше приложение. Все ли находится в одной сборке или у вас есть несколько сборок, каждая из которых содержит разные части бизнес-логики? Это повлияет на то, где нужно будет определить глобальный класс и возможно ли это вообще. Если все находится в одной сборке или у вас есть общая сборка, на которую ссылаются все остальные, вы могли бы сделать что-то вроде этого: codeproject.com/KB/cs/findcurrentappcontext.aspx но я бы использовал шаблон Singleton вместо точного копирования кода. В противном случае вам, вероятно, пришлось бы передавать форму всей вашей бизнес-логике.
5. Могу ли я поместить все потоки и формы внутри пользовательского класса ApplicationContext? Это уместно?
Ответ №2:
Запустите их в Main()
перед созданием пользовательского интерфейса.