> Почему и не могу понять - вроде МФСевый класс, а работает > через какую-то ж..., типа AfxBeginThread. > Почему нельзя было сделать так, чтобы объявил экземпляр > класса, а сам поток запускал через, типа > CWinThread.Start(), CWinThread.Kill() с возможностью > доступа, как к публичным свойствамна ходу, так и из него - > ко всем внешним переменным обычным образом?
Если бы дали создавать самому, то нашлись бы толпы программистов, создающих этот объект в автоматической памяти или забывающих удалять объект после завершения потока при создании в динамической памяти. Так же AfxBeginThread передается объект, способный создать потоковый объект так, как ей нужно. С инициализацией его чуть хуже, но вполне можно создать поток с CREATE_SUSPENDED, проинициализировать все, что нужно, через указатель, который вернула AfxBeginThread, и разбудить поток (штатная техника, описанная в MSDN) - это если хочется избежать глобальных переменных, конечно. Ну и доступ есть как ко внешним переменным из объекта, так и к его полям, только при доступе извне нужно быть уверенным, что он в этот момент существует.
CDocument и CView ведь тоже самостоятельно не создаются из тех же соображений удобства для фреймворка.
И увидит ли она переменные и методы класса?
Никогда так на делал - ThreadProc глобальная, и все. А тут тред запускается из диалога и должен непрерывно печатать результаты вычислений в него же, при этом, на экране непрерывно должен висеть МесседжБокс с кнопкой останова вычислений.
Конечно может05.09.09 05:03 Автор: void <Grebnev Valery> Статус: Elderman
Я же писал: некий девайс определяется, как клава и сливает данные. Задача - принять данные не дав юзеру нажать на клаву или заблокировав ее. Все это должно быть в 1м ехе без драйверов и длл.
Пока вариант 1. Проблема в том, что передача может завершиться признаком конца, а может и зависнуть. Значит, все время должно висеть сисмодальное окно с кнопкой останова и предупреждением, чтобы не трогали клаву.
Счас все работает так: старт приема запускает поток в котором в цикле крутится GetAsyncKeyState и выводит сисмод диалог. Если кликнули стоп - устанавливается флаг "остановить". Если передача завершилась нормально, поток отправляет сисмод диалогу ONCANCEL.
Callback функции не могут быть мемберами классов27.08.09 13:29 Автор: Den <Денис Т.> Статус: The Elderman
Но ты можешь хранить в памяти таблицу соответствия хенлов процессов и ссылок на экземпляры объектов, функции-мемберы которых ты можешь вызывать из callback функции.
WndProc - может, а другие - нет?27.08.09 16:35 Автор: Zef <Alloo Zef> Статус: Elderman
> Может все-таки ты имеешь ввиду эту функцию?: > http://msdn.microsoft.com/en-us/library/ms633573(VS.85).asp > x > > Так она не может быть функцией-членом класса. Ну, так все равно, механизм ее использования есть - она же может вызывать ф-ции члены - обработчики сообщений. Если поток с очередью сообщений - все так же, если без - сделали бы вызов единственной ф-ции, которую и переопределять.
Конечно может!27.08.09 21:03 Автор: Den <Денис Т.> Статус: The Elderman
> Ну, так все равно, механизм ее использования есть - она же > может вызывать ф-ции члены - обработчики сообщений. Если > поток с очередью сообщений - все так же, если без - сделали > бы вызов единственной ф-ции, которую и переопределять.
Переопредели CWinThread::InitInstance без создания окна, возвращающий FALSE, и будет ровно такой же эффект. Только это геморрой ради геморроя, лепить класс ради вызова единственной функции.
Не считая варианта static member, что не считается. Хотя никто не мешает передать в поток указатель на объект и первой/единственной строчкой потоковой функции дернуть через него нормальную функцию (а если оформить это макросом, то и совсем незаметно получится).
> И увидит ли она переменные и методы класса? > Никогда так на делал - ThreadProc глобальная, и все. А тут > тред запускается из диалога и должен непрерывно печатать > результаты вычислений в него же, при этом, на экране > непрерывно должен висеть МесседжБокс с кнопкой останова > вычислений.
Кстати, если речь о MFC, то рабочие потоки с интерфейсом с большими нюансами взаимодействуют, через шаг нарываясь на ассерты. Может быть, стоит рассмотреть вариант с интерфейсным потоком (который потомок CWinThread).
Дык я CWinThread и юзаю26.08.09 12:52 Автор: Zef <Alloo Zef> Статус: Elderman
Почему и не могу понять - вроде МФСевый класс, а работает через какую-то ж..., типа AfxBeginThread.
Почему нельзя было сделать так, чтобы объявил экземпляр класса, а сам поток запускал через, типа CWinThread.Start(), CWinThread.Kill() с возможностью доступа, как к публичным свойствамна ходу, так и из него - ко всем внешним переменным обычным образом?
там чуть хуже26.08.09 17:05 Автор: dl <Dmitry Leonov> Отредактировано 26.08.09 17:13 Количество правок: 4
> Почему и не могу понять - вроде МФСевый класс, а работает > через какую-то ж..., типа AfxBeginThread. > Почему нельзя было сделать так, чтобы объявил экземпляр > класса, а сам поток запускал через, типа > CWinThread.Start(), CWinThread.Kill() с возможностью > доступа, как к публичным свойствамна ходу, так и из него - > ко всем внешним переменным обычным образом?
Если бы дали создавать самому, то нашлись бы толпы программистов, создающих этот объект в автоматической памяти или забывающих удалять объект после завершения потока при создании в динамической памяти. Так же AfxBeginThread передается объект, способный создать потоковый объект так, как ей нужно. С инициализацией его чуть хуже, но вполне можно создать поток с CREATE_SUSPENDED, проинициализировать все, что нужно, через указатель, который вернула AfxBeginThread, и разбудить поток (штатная техника, описанная в MSDN) - это если хочется избежать глобальных переменных, конечно. Ну и доступ есть как ко внешним переменным из объекта, так и к его полям, только при доступе извне нужно быть уверенным, что он в этот момент существует.
CDocument и CView ведь тоже самостоятельно не создаются из тех же соображений удобства для фреймворка.
> Ну и > доступ есть как ко внешним переменным из объекта, так и к > его полям, только при доступе извне нужно быть уверенным, > что он в этот момент существует.
Нет там никакого доступа и быть не может. Потоки в разных адресных пространствах сидят, у них тока длл общие. Меня вчера на ночь глядя переклинило, что pParam в AfxBeginThread - int, тогда, как он LPVOID. Оно там на другое место, где я случайно букву впечатал, ругалось, что не может к инту преобразовать, а я на pParam думал. Вот, я и не мог въехать, как же так - если указатель передается, как число, тада и все остальные указатели и переменные должны быть валидны, но как? Компилер сам процедуру пересчета адресов подставляет?
Поутру продрав глаза обнаружил опечатку и то, что pParam - LPVOID. В бошке прояснилось: AfxBeginThread отображает pParam в тред. Естессно, в списке параметров тада указатели передавать нельзя. Тока числа и хендлы.
Так ты используешь CreateRemoteThread ? [upd]27.08.09 13:31 Автор: Den <Денис Т.> Статус: The Elderman Отредактировано 27.08.09 13:42 Количество правок: 1
[upd]
Забудь про int в API вызовах. За редким исключением, большинство целочисленных параметров DWORD или LONG POINTER, flat'овый сегмент каждого процесса в 32-битных ОСях простирается на 3Гб виртуального адресного пространства.
С разбегу я ее использую!27.08.09 16:38 Автор: Zef <Alloo Zef> Статус: Elderman
Я же ясно написал, что GetAsyncKeyState в цикле кручу. Ну нафига мне ремоут тред в совершенно легальной читалке какого-то изредка подключаемогок компу девайса?
Я спросил, потому что ты написал про потоки в разных адресных пространствах.27.08.09 17:19 Автор: Den <Денис Т.> Статус: The Elderman Отредактировано 27.08.09 17:20 Количество правок: 1
Когда AfxBeginThread отображает указатель блока аргументов в память потока, как она узнает резмеры этого блока? Или его размер ограничен страницей памяти? (Надо полагать, в память потока может мапится только страница целиком)
А если блок не в начале страницы?! Нигде ведь не сказано, что память под блок должна выделяться маллоком и в МСДНском примере этого нет.
Ниче не понимаю! Получается, что все потоки процесса сидят в общей памяти? Тада нахрена гиморой с передачей указателя на блок аргументов? Мелкомягкие в очередной раз хотели сделать умную рожу при идиотской игре? Или у них компилер такой умный, что несмотря на то, что я передаю указатель LPVOID, он смотрит чтобыло преобразованно к этому виду и определяет размеры, а потом размещает ЭТО в точности в начале страницы? Нереально...
нет никакой памяти потока (не считая TLS)27.08.09 12:13 Автор: dl <Dmitry Leonov> Отредактировано 27.08.09 12:19 Количество правок: 3
...но чтобы им пользоваться нужны дополнительные усилия. По умолчанию все потоки одного процесса живут в одном адресном пространстве, это азбука. Первая же строчка описания СreateThread в MSDN:
Creates a thread to execute within the virtual address space of the calling process.
> Ниче не понимаю! Получается, что все потоки процесса сидят > в общей памяти? Тада нахрена гиморой с передачей указателя > на блок аргументов? Мелкомягкие в очередной раз хотели > сделать умную рожу при идиотской игре?
Возможность передачи информации через параметр, а не через глобальные переменные - это идиотская игра?
> Возможность передачи информации через параметр, а не через > глобальные переменные - это идиотская игра?
Это нормально для плейн-С чтобы передать переменный список параметров. А для МФС это - дичь пернатая. Если уж классы, то свойства и методы через точечку или стрелочку. А за создание объекта "поток" через AfxBeginThread надо отрывать гениталии! Если поток - класс, то почему его надо создавать через невесть какую ж...?
Речь не о том, что я не умею работат с потоками, я знаю, как это делается в плейн-С. Но сочиняя некую приблуду для заказчика я решил, что плейн-С, это не цивилизованно, мало ли кому чего потом переделать захочется - плейн-С никто знать не обязан. И тут я вижу, что в МФС имеется набор: каменный топор и фиберглассовое топорище... Причем, чтобы его насадить, надо еще в камне дырку самому проколупать!
Конечно, "партайгеноссе Борланд", это другая крайность, когда обертки на все случаи жизни в 10 раз больше конфетки, но дожен же быть кто-то, кто хоть немного приблизится к "золотой середине"! Почему все Мастдайство состоит из одних крайностей? Либо - крайний примитив, когда море кода приходится писать руками, либо - ради таблички в 3 строчки подымают SQL-сервер...