134 / 129 / 59
Регистрация: 16.06.2013
Сообщений: 523
|
|
1 | |
Передача функции в главный поток в консольном приложении16.09.2017, 05:02. Показов 4624. Ответов 20
Метки нет (Все метки)
Здравствуйте! Посмотрите пожалуйста свежим взглядом на проблему, ибо я, похоже, зациклился на одном варианте, и не вижу решения. Ну, или как обычно туплю в очевидных для всех вещах... =_=
Суть проблемы, если упростить всю систему, вот в чём. Есть консольное приложение, в нём есть поток, который выполняет определённое действие и завершается, и, по результатам его работы, мне нужно запустить определённую функцию, которая должна работать уже в основном потоке. В приложениях WindowsForms я решал такую проблему методом вызова BeginInvoke, для основной формы, а тут я немножко подзавис. Заранее спасибо за советы.
0
|
16.09.2017, 05:02 | |
Ответы с готовыми решениями:
20
Передача объекта обратно в главный поток из другого потока Получение значения из фонового потока и передача его в главный поток Построение графика функции в консольном приложении Код который работает в консольном приложении в приложении Windows Forms выдает ошибку |
3654 / 2567 / 717
Регистрация: 02.08.2011
Сообщений: 6,928
|
|
16.09.2017, 07:36 | 2 |
Для таких вещей предусмотрен механизм событий.
1
|
134 / 129 / 59
Регистрация: 16.06.2013
Сообщений: 523
|
||||||
16.09.2017, 07:51 [ТС] | 3 | |||||
IamRain, Эммм... Может я что-то путаю, но я пробовал реализовать это с событием, и функция, вызванная им всё-равно шла во вторичном потоке, а не в основном (Сорри, за кривой код, он из моего тестового оконного приложения, в котором я ковыряю эту проблему):
Кликните здесь для просмотра всего текста
При выводе в листбокс, информации о цикле, после его запуска, он показывает что цикл работает, хотя по идее, цикл должен был завершиться и функция ddd(); должна была выполниться в основном потоке.
0
|
3654 / 2567 / 717
Регистрация: 02.08.2011
Сообщений: 6,928
|
||||||
16.09.2017, 08:06 | 4 | |||||
Вот такой пример:
1
|
134 / 129 / 59
Регистрация: 16.06.2013
Сообщений: 523
|
|
16.09.2017, 08:21 [ТС] | 5 |
IamRain, хм... Чёт я слегка запутался. Похоже я действительно что-то напутал, пока у себя ковырял код. Спасибо большое, ваш вариант пашет 100%. Буду разбираться.
0
|
3654 / 2567 / 717
Регистрация: 02.08.2011
Сообщений: 6,928
|
||||||
16.09.2017, 08:49 | 6 | |||||
Сообщение было отмечено Захарка как решение
Решение
В приложениях с GUI для вызова методов в потоке GUI используется так называемый SyncronizationContext, а именно
это делает SyncronizationContext.Post method. В который передается делегат, который должен быть вызван. Control.BeginInvoke внутри себя как раз таки и использует этот SyncronizationContext.Post. В консольных приложениях нет каких-то особо выделяющихся потоков, и поэтому нет надобности в контексте синхронизации, т.е в консоли:
1
|
134 / 129 / 59
Регистрация: 16.06.2013
Сообщений: 523
|
|
16.09.2017, 09:03 [ТС] | 7 |
IamRain, Кхм... Я ещё раз перепроверил ваш вариант, и чёт нифига... Я попробовал несколько вариантов, но так и так, событие выполняется в потоке созданном в классе.
0
|
3654 / 2567 / 717
Регистрация: 02.08.2011
Сообщений: 6,928
|
|
16.09.2017, 09:05 | 8 |
Захарка, все же это нерабочее решение, потому что может быть и такой результат:
Вообщем, нужно разбираться с контекстами синхронизации.
1
|
134 / 129 / 59
Регистрация: 16.06.2013
Сообщений: 523
|
|
16.09.2017, 09:07 [ТС] | 9 |
IamRain, это да... Сейчас просились ещё, и на свежую голову буду думать... Спасибо большое, за помощь!
0
|
3654 / 2567 / 717
Регистрация: 02.08.2011
Сообщений: 6,928
|
|
16.09.2017, 09:20 | 10 |
Захарка, вам очень важно, чтобы код выполнялся в каком-то конкретном потоке?
Второй пост был написан исходя из того, что я решил вам нужна просто необходимость уведомления о завершении какого-либо действия. Разве важно то, в каком потоке будет происходить обработка результатов работы?
0
|
1150 / 858 / 263
Регистрация: 30.04.2009
Сообщений: 3,598
|
|
16.09.2017, 10:16 | 11 |
Чтоб вы понимали... Чудес не бывает, и для того, чтобы можно было выполнить что-то в определенном потоке, в этом потоке просто есть бесконечный цикл, который проверяет наличие "задач", которые ему прислали и в порядке очереди их выполняет.
Реализация в зависимости от технологии (WinForms, WPF и т.д.) отличается, но смысл один и тот же. А SynchronizationContext - это просто общая абстракция, которая сделана для унификации выполнения тасков. Написал бы простенькую реализацию для примера, но не вижу смысла так извращаться в консольном приложении.
0
|
3654 / 2567 / 717
Регистрация: 02.08.2011
Сообщений: 6,928
|
|
16.09.2017, 10:25 | 12 |
Цикл обработки сообщений присутствует только для GUI потоков, поскольку, у них есть свои особые задачи по работе с интерфейсом. Остальным же потокам (worker, io) это ни к чему.
0
|
134 / 129 / 59
Регистрация: 16.06.2013
Сообщений: 523
|
|
16.09.2017, 15:48 [ТС] | 13 |
IamRain, так, я проспался, и могу примерно сформулировать, зачем мне такие. У меня в проекте есть ядро Авесомиума, использующееся в консольном режиме. Все обращения к нему могут выполняться только в main-потоке, но это решаемо средствами самого авесомиума. В итоге получается такая примерно фигня:
1) Класс ожидания действий имеет свой поток. 2) По наступлению определённого момента, он вызывает класс работы с сайтом. 3) У него есть свои потоки, и он шлёт классу работы с браузером Java-запросы на выполнение. 4) Класс работы с браузером выполняет скрипты в main-потоке, и возвращает полученные данные в класс работы с сайтом. В итоге получается косяк - класс работы с сайтом висит в потоке класса ожидания действий, а класс работы с браузером может вызвать функцию обработки вытянутых данных только для main-потока. А, чтобы всё исправить, нам всего-лишь нужно чтобы класс работы с сайтом сам был в main-потоке. Таким образом, мне нужно вызывать его функции, передав их в мейн поток. Примерно так.
0
|
134 / 129 / 59
Регистрация: 16.06.2013
Сообщений: 523
|
|
16.09.2017, 16:39 [ТС] | 15 |
IamRain, Там сложно. Дело в том, что у авесомиума есть класс WebView, который является оболочкой браузера, и позволяет выполнять скрипты, и делать прочие интересные вещщи. И он имеет метод BeginInvoke, но! Он у меня есть только в классе общения с браузером, и используется только внутри него, так как большую часть времени его не существует. Я, конечно, могу использовать костыльный метод, создав экземпляр класса WebView, в одном из файлов, и написав оболочку, для выполнения, через него обращения к main-потоку, но это как-то печально. Надеялся, что есть адекватный метод решения данной проблемы...
Спасибо вам большое за помощь.
0
|
3654 / 2567 / 717
Регистрация: 02.08.2011
Сообщений: 6,928
|
|
16.09.2017, 16:55 | 16 |
Ну, на SO есть еще один вроде бы толковый ответ:
1
|
134 / 129 / 59
Регистрация: 16.06.2013
Сообщений: 523
|
|
16.09.2017, 16:59 [ТС] | 17 |
IamRain, спасибо большое, буду разбираться.
0
|
3654 / 2567 / 717
Регистрация: 02.08.2011
Сообщений: 6,928
|
|
16.09.2017, 17:07 | 18 |
У Stephen-а Cleary имеется два решения.
1
|
138 / 138 / 53
Регистрация: 14.06.2016
Сообщений: 467
|
|
16.09.2017, 17:26 | 19 |
0
|
134 / 129 / 59
Регистрация: 16.06.2013
Сообщений: 523
|
|
16.09.2017, 20:04 [ТС] | 20 |
Товарищи! Дико извиняюсь! Я - полный идиот, который никогда не дочитывает до конца >_<. В своё оправдание могу сказать только то, что я весь вечер и ночь над этим ковырялся, и голова совсем не варила в тот момент. Простите, за потраченное время. Авесомиум, при запуске ядра, передаёт контекст синхронизации, для своего потока. Ещё раз сорри =(.
0
|
16.09.2017, 20:04 | |
16.09.2017, 20:04 | |
Помогаю со студенческими работами здесь
20
Передача в поток, функции с двумя параметрами Главный поток и вторичный Дополнительный поток тормозит главный BackgroundWorker блокирует главный поток Приостановить главный поток до закрытия формы Получить результат из потока в главный поток Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |