Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Двусторонний вызов функций в классах  (Прочитано 17903 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Junk
Гость
« : 22-11-2005 15:55 » 

Есть два класса: CMyDlg и CMySocket, находящихся в разный файла MyDlg.cpp и MySocket.cpp соответственно.
В классе CMyDlg у меня находится переменная MySocket socket, поэтому я могу в диалоге свободно вызывать функции сокета (socket.SendData(Data,Port,Addr)). Но когда приходит новое сообщение, вызывается функция сокета OnReceive и я никак не могу передать полученную информацию диалогу для отображения.
Совет объявить в классе сокета указатель на диалог CDialog* pDlg и переадресовывать его на свой диалог ((CMyDlg*)Dlg)->SetDlgItemText(...) не получается.

Что делать???

Может проблема в том, что в классе сокета отсутствует указатель на окно m_hWnd?
Записан
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #1 : 22-11-2005 16:19 » 

Junk,

А почему не использовать PostMessage или что-то в этом духе?
Ну или тогда надо в каком-то основном (для твоих классов CMyDlg и CMySocket) классе (напр. CMyApp)иметь переменную, указывающую на диалог, с одной стороны, а в классе CMySocket - переменную, указывающую на этот основной класс CMyApp, с другой. Тогда ты сможешь безболезненно пересылать любые данные.
А вносить в класс CMySocket указатель на CMyDlg очень нездорово, т.к. у тебя получается замкнутый круг инклудов, а это до добра еще никого не доводило Ага
Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #2 : 22-11-2005 16:42 » 

Вообще - то это неправильно - использовать сокетный класс таким образом.
Асинхронный прием, который делает сокет должен заполнять некий буфер и давать возможность узнавать об этом другим.
Для это придуман механизьм CreateEvent (в данном случае я с Малой не согласен, Пост и Сенд месадж функции для таких вещей не предназначены и сильно тормозят систему)

Должен быть некий поток, который стоит и ждет и который имеет возможность сделать считывание данных из буфера если туда положены данные по сообщению присланному от класса сокета.
Когда данные считаны, можно посылать их классу диалога как угодно.
Записан

А птичку нашу прошу не обижать!!!
Junk
Гость
« Ответ #3 : 22-11-2005 18:19 » 

Гром, расскажи с примером, пожалуйста. Почитал в руководстве про функцию CreateEvent, но не понял как передавать в диалог сообщение, что присланы данные от класса сокета - где и что надо описывать?
Записан
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #4 : 23-11-2005 09:48 » 

Гром,

насчет PostMessage (причем специально не Send - это точно завесит все и надолго) - я дала просто как возможность сообщить одному классу о том, что второй имеет ему что-то сказать, как говорили в Одессе Ага Извиняюсь, конкретно о сокет-классе я тут не подумала.
Насчет Eventа - тут баба Яга против Ага Я тут как раз совсем недавно имела удовольствие их использовать посему и возражаю, причем громко Ага . Дело в том, что с их помощью можно сообщать другим о том, что сейчас что-то происходит. Т.е. пришел пакет - сокет выставил Event("пакетУжеТут"). А когда диалогу что-то надо, он спрашивает, существует ли такой Event в системе. Если да - он берет данные из общей области памяти, если нет - делает свои дела дальше.
Но в данном случае смысл заключается не в этом - тут надо по прибытии пакета сообщить диалогу, что данные уже на месте. Т.е. если и использовать Event, то тогда в диалоге надо стартовать таймер, который будет периодически опрашивать систему на предмет наличия соответствующего флага. ПО мне лучше в этом случае или связь с диалогом через какой-то общий (или основной) класс или послать сообщение типа "пакетТут", по получении которого диалог пойдет к сокету и возьмет нужную инфу.

Если я неправа - поправь, буду очень благодарна.
Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #5 : 23-11-2005 10:54 » 

Junk - примеров масса в том числе в интернете.
Есть две функции

SetEvent - выставить событие
ResetEvent - сбросить событие.
Во всех местах где тебе доступен HANDLE который ты получил при создании события у тебя есть возможность его посмотреть или проверить....

Например


{
HANDLE hEvent = CreateEvent(0,False,True,0);
}

{

      WaitForSingleObject(hEvent,INFINITE); Сидим ждем события....
      ResetEvent() // Произошло событие - сбросим его дабы повторно не реагировать....
}

{
     SetEvent(hEvent);


}
Записан

А птичку нашу прошу не обижать!!!
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #6 : 23-11-2005 10:56 » 

Малая....

Хм.
Все дело в простоте.
Ставь в диалоге некий процесс - допустим в инит диалоге.

В нем ставь вышеупомянутую WaitForSingleObject с таймером на 1000. Он и будет ждать события.
Как только что-то произойдет, то процесс отреагирует, т.е. споймает его.

Обработка может быть просто такой.
При создании потока передаем указатель на сам диалог в качестве параметра.
После того как мы получили событие - выывем обработчик сокета из диалога, и пишем результаты в нужные окна и т.д.
Просто в задачу сильно не вникаю... Жаль занят.
Записан

А птичку нашу прошу не обижать!!!
Junk
Гость
« Ответ #7 : 23-11-2005 10:59 » 

А какое значение нужно указать в первом параметре PostMessage (handle окна назначения)? Ведь в этом-то и проблема, что с классе CMySocket отсутствует указатель на окно диалога CMyDlg!
Записан
Junk
Гость
« Ответ #8 : 23-11-2005 11:14 » 

Да, я согласен с Малой - нужно будет постоянно опрашивать о приходе события WaitForSingleObject(), что запарно. Как тогда оповестить диалог с помощью PostMessage если в классе CMySocket отсутствует указатель на окно диалога CMyDlg?
Записан
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #9 : 23-11-2005 11:45 » 

Junk,

HWND_BROADCAST - говорит о том, что это сообщение должно идти ко всем окнам. (PostMessage)
Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #10 : 23-11-2005 11:57 » 

Цитата
Да, я согласен с Малой - нужно будет постоянно опрашивать о приходе события WaitForSingleObject()


Эге - я так смотрю народу учиться лень, а тем более читать внимательно.
Я честно сказать непонял как это опрашивать функцию?
Согласен с Малой ? Делай как она пишет, когда завалишь буфер на приеме и начнешь упускать пакеты - вернешься.
Запарно тебе говоришь Улыбаюсь

HANDLE harr[2] = {hEventSocrt, hEventExit};

while(1)
{
switch(WaitForMultipleObkect(harr,INFINITE) )
{
case WAIT_OBJECT_0:
             /// Обработка сокета
     break;
case WAIT_OBJECT_0+1:
    return 0;

}
}


Вот это код для опроса сокетов. При этом поток с этим кодом ждет вегда. Всегда работает как ожидающий события.
Если тебе надо выходить - ты делаешь посылку спец события по выходу, как видно в примере второй хендл.
Если приходит сокет - обрабатываешь его.

А хотя чего я распигаюсь, тебе ж потом локти кусать Улыбаюсь


Малая - надеюсь понятно?

}
Записан

А птичку нашу прошу не обижать!!!
Hooter
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 23-11-2005 12:56 » 

Использование PostMessage при обработке событий сокета чревато как минимум двумя проблемами:

1. Очередь сообщений приложения пополняется новым сообщением от сокета. Обработка данных, полученых от сокета, занимает какое-то время, а значит, приложение "подвешивается" на время обработки.

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

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

Мне нравится способ Грома - просто и удобно.

ЗЫ. Использование HWND_BROADCAST вообще слабо обосновано, потому что это сообщение ислользуется для рассылки сообщения всем зарегистрированным окнам. То есть для обмена сообщениями между приложениями. В рамках одного приложения использовать HWND_BROADCAST, как мне кажется, неправильно и неэффективно.
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #12 : 23-11-2005 16:07 » 

А я бы сначала поближе познакомился с CMySocket - например взглянул бы на его исходники. Может проблемы и не существует вовсе. Может ему можно указатель на CMyDlg предеать али callback фукцию.
А так это всё гадание на кофейной гуще - какой способ лучше подойдёт к черной коробочке.

зы Всё остальное - по поводу инклудов и пр - суеверия. Post/SendMessage не подходят. Если это то, что предпололжил Гром, то однозначно новый тред и слежение. С любой удобной синхронизацией - самая простая конечно же WaitForSingleObject.
Кстати, Гром, а с чего ты взял, что это именно ТОТ сокет - из условия ОДНОЗНАЧНО этого не следует Ага
« Последнее редактирование: 23-11-2005 16:13 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #13 : 24-11-2005 11:14 » 

Гром, Hooter,

начинаю оправдываться Ага
Во-первых, я не знала того, что написал Hooter.
Во-вторых, HWND_BROADCAST можно использовать как крайний случай, но при этом надо правильно определять пользовательские сообщения через WM_USER + число, чтобы они не повторялись и не дублировали стандартные сообщения (в пределах одного приложения это реально).
Из всего вышеизложенного следует, что:
во-первых, мое предложение решения задачи неверно (PostMessage - путь),
во-вторых, тогда предложенное Громом решение в любом случае самое безобидное (никаких дополнительных связей классов между собой).
Спасибо за инфу!
Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #14 : 24-11-2005 12:02 » 

Малая - все именно так - никаких усложнений. Сокеты - это реальное время, как бы нам не хотелось обратного.
Функция ждущая в отдельном потоке лучше чем любой тайминг или любой опрос, и даже чем блокирующее соединение, по причине легкости в управлении.


Джон - не понял вопроса про тот сокет Не понял  Что сие значит.
Задача программера обеспечить правильную реакцию.
На всамом деле - я понял только одно, люди совершенно не умеют пользоваться сокетами, но по любому отвечал на заданный вопрос о синхронизации.

НА деле ВинСокет написан на базе БСД сокет интерфейса, который имеет такую функцию как select  с помощью которой можно очень классно уживаться безо всяких событий - просто ставить на ожидание большое колличество сокетов получая в ответе из селекта какой из них получил данные, но это написано в статьях на сайте и повторяться я не хотел....Улыбаюсь
Записан

А птичку нашу прошу не обижать!!!
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #15 : 24-11-2005 13:21 » 

Гром, эт я прикололся по поводу "Теста на логическое мышление" Улыбаюсь
Ведь из вопроса не следует явно, что это именно ТЕ самые сокеты. А может быть это просто какая-нить message loop, да и вообще я CMySocet могу назвать всё, что угодно.. Да и не важно это всё. Я так думаю у Junk проблемы с двумя классами, которые должны работать друг с другом. Тем более что он уже нечто подобное спрашивал, ИМХО.
Проблема стандартная и есть разные способы как сделать развязку. Только действительно полезный совет на основании инфы в вопросе ИМХО дать нельзя. Можно конечно фантазироваить по поводу возможных решений (я кстати согласен, что если речь идёт о "прослушивании" сокета, то только тред и только синхронизация), но всё-таки - для простого хорошего решения этого мало. DIXI
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #16 : 24-11-2005 13:50 » 

но всё-таки - для простого хорошего решения этого мало.


Поясни пожалуйста....
Не понял, что такое простое и хорошее решение?
Записан

А птичку нашу прошу не обижать!!!
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #17 : 24-11-2005 16:13 » 

Простое и хорошее - при минимуме кода (ресурсов и тп) добиться наилучшего результата.

Есть условие - проблема:

когда приходит новое сообщение, вызывается функция сокета OnReceive и я никак не могу передать полученную информацию диалогу для отображения. Совет объявить в классе сокета указатель на диалог CDialog* pDlg и переадресовывать его на свой диалог ((CMyDlg*)Dlg)->SetDlgItemText(...) не получается.

Просто и понятно - НЕ ПОЛУЧАЕТСЯ! А почему? ЧТо конкретно не работает? Что не получается?
Понятия не имея, что представляет собой CMySocket - посыпались советы: "PostMessage", "Асинхронный прием", "CreateEvent". Классные способы, разговору нет. Но как определить какой лучше подойдёт в данном случае? А почему бы не просто callback функция? И не надо никого ждать! Кто вам сказал, что в CMySocket нет треда? А может он там есть? Ведь посмотри, ты вернулся практически к проблеме в вопросе в #6 "При создании потока передаем указатель на сам диалог в качестве параметра.", но ведь насколько я понял именно с этим у Junk и проблема. Особенно если тред находится в CMySocket - что собственно говоря было бы логично, если бы CMySocket был именно тем классом, какаим мы его представляем и который должен работает так как нам кажется тд и тп (опять предположения). Ну давайте тогда уж быть последовательными - если данные передаются из другого треда, то надо ещё ввести и синхронизацию - хотя бы через critical section. И тд и тп
А не слишком ли сложные ответы для казалось бы простого вопроса? Если не вдаваться в рассуждения на тему - а для чего это всё может быть использовано. Может проще спросить? А что он делает и нафига он нужен этот CMySocket?

Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Junk
Гость
« Ответ #18 : 22-12-2005 11:56 » 

Гром, благодарю за объяснения.
Полезность функций ожидания событий осознал!

Не могу понять только куда их вписывать эти функции (WaitFor...Object):
Для главного диалога, в котором отображается процесс приема информации, нет функции OnIdle, как для приложения, в котором он вызывается. В какую еще функцию можно вписать ожидание событий прихода сообщений???
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines