Новые сообщения [новые:0]
Дайджест
Горячие темы
Избранное [новые:0]
Форумы
Пользователи
Статистика
Статистика нагрузки
Мод. лог
Поиск
|
28.01.2017, 05:44
|
|||
---|---|---|---|
Вызов Callback из C-библиотеки |
|||
#18+
Описание из opal.dll автор... OpalMessageAvailableFunction m_messageAvailable; /**< If non-null then this function is called before the message is queued for return in the GetMessage(). See the OpalMessageAvailableFunction for more details. */ ... 'If non-null then this function is called before 'the message is queued for return in the 'GetMessage(). See the 'OpalMessageAvailableFunction for more details. 'IntPtr m_messageAvailable As Long /** Function called when a message event becomes available. This function is called before the message is queued for the GetMessage() function. A return value of zero indicates that the message is not to be passed on to the GetMessage(). A non-zero value will pass the message on. Note that this function will be called in the context of different threads so the user must take care of any mutex and synchonisation issues. If the user subsequently uses the GetMessage() then the message will have been serialised so that there are no multi-threading issues. A simple use case would be for this function to send a signal or message to the applications main thread and then return a non-zero value. The main thread would then wake up and get the message using GetMessage. */ typedef int (*OpalMessageAvailableFunction)( const OpalMessage * message /**< Message that has become available. */ ); В VB6 у меня под это дело некогда была вымучена такая хитрая конструкция: Инициализация Callback-а отправляется в dll в следующем виде: Код: vbnet 1. 2. 3. 4.
Сама Callback - ф-ция реализована так: Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20.
Из самой OpalMessageAvailableFunction насколько я понял сообщение забрать нельзя или очень нежелательно (другой поток?), поэтому используем тик таймера. Интервал таймера выставлен =1 миллисекунда Ну и собственно он забирает сообщение как только так сразу (единственный поток не висит и таймер не долбит) Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
Как это в VB.Net сделать? Пока туплю, c делегатами вроде чуть игрался. Задекларировать делегата Создать New делегата AddressOf OpalMessageAvailableFunction этого делегата запомнить глобальной переменной (чтоб мусорщик не съел) и бухнуть в m_messageAvailable (IntPtr). ??? путаюсь чего-то Есть некие исходники-обертка C# под это дело. Там есть такие конструкции. Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.
Но чет не очень похоже на мою VB6-конструкцию, которую вымучивал долго но при этом работает как часы. Сам автор .Net кода в тест-примере это никак не использует, и не факт что у него это вообще работает. ... |
|||
:
Нравится:
Не нравится:
|
|||
|
29.01.2017, 20:35
|
|||
---|---|---|---|
Вызов Callback из C-библиотеки |
|||
#18+
Вернулся к этому вопросу. В принципе переписал VB6 код. Код: vbnet 1. 2. 3. 4.
Инициализируем CallBack так: Код: vbnet 1.
Ловим вот так: Код: vbnet 1. 2. 3. 4. 5.
Form1 - это конкретная форма Код: vbnet 1. 2. 3. 4. 5. 6. 7.
Код таймера (.Interval=1(миллисекунда)) такой Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
MyMessageAvailable исправно ловит сообщения (пишет в Debug слово "message") Но возникла проблема: таймер срабатывает только один раз, потом он выключается(из-под себя) и больше уже не срабатывает. Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
В VB6 это работало. Что я не догоняю? Почему Form1.TimerGetMes.Enabled = True повторно не срабатывает и не вызывает тика таймера? ... |
|||
:
Нравится:
Не нравится:
|
|||
|
29.01.2017, 20:47
|
|||
---|---|---|---|
Вызов Callback из C-библиотеки |
|||
#18+
Причем что интересно нажимаем Код: vbnet 1. 2. 3.
Пишет True, а Код: vbnet 1.
при этом не вызывается. Как такое может быть? ... |
|||
:
Нравится:
Не нравится:
|
|||
|
29.01.2017, 20:54
|
|||
---|---|---|---|
Вызов Callback из C-библиотеки |
|||
#18+
Дмитрий77, Я бы вместо включения постоянно таймера в процедуре (а таймер может не успеть обработать сообщение, как придут опять в работу, т.е. его опять включат), сделать так: 1) В callback процедуре заносить приходящие сообщения в очередь Queue (ещё лучше, если это будет потокобезопасная очередь и сбор будет в отдельном потоке) 2) Таймер в форме может работать постоянно ~10 мс и если очередь не пуста, читать данные из неё Сейчас сказать, почему таймер сломался сложно, возможно есть эксепшены, которые не выводятся и не рушат приложения. Посмотрите во вкладках "Вывод" и "Интерпретация", может там их найдёте. ... |
|||
:
Нравится:
Не нравится:
|
|||
|
29.01.2017, 21:09
|
|||
---|---|---|---|
Вызов Callback из C-библиотеки |
|||
#18+
+ в шарповском варианте, у делегата есть параметр: Код: vbnet 1.
а у вас без параметров: Код: vbnet 1.
... |
|||
:
Нравится:
Не нравится:
|
|||
|
29.01.2017, 21:34
|
|||
---|---|---|---|
Вызов Callback из C-библиотеки |
|||
#18+
VSVLADВ callback процедуре заносить приходящие сообщения в очередь Queue CallBack процедура сообщения не читает. Она только вызывается как сообщение приходит. Из нее надо вернуть 1 (принимаем сообщение и можем прочесть его через GetMessage) и посылает сигнал, что есть чего читать (в моем случае это включение таймера на Form1). А таймер уже вызывает GetMessage через 1 мс. VSVLADа таймер может не успеть обработать сообщение, как придут опять в работу, т.е. его опять включат Ничего страшного, тик таймера читает все сообщения(Do Loop, их уже может быть несколько) и по-любому его отключает в процедуре тика. Вопрос в том, что включение таймера из CallBack срабатывает только один раз, т.е. .Enabled=true то он и дальше становится, а тиков не вырабатывает. В VB6 это все работало как часики. VSVLAD2) Таймер в форме может работать постоянно ~10 мс и если очередь не пуста, читать данные из неё Да так можно, и CallBack тогда вообще не нужен. Но постоянно долбать таймер я не хочу, очень уж это неграмотно. Есть разница между "постоянно долблю с задержкой 10мс" или "вызываю по необходимости с задержкой 1мс". Можно наверно попробовать API-таймер с сохранением логики, дабы не гадать что там в .Net не так. Еще, мне надо чтоб GetMessage() выполнялось и делало обработку в контексте потока Form1, а вот в каком потоке вызывается CallBack (из которого я стартую таймер) в случае .Net это ХЗ. ... |
|||
:
Нравится:
Не нравится:
|
|||
|
29.01.2017, 21:44
|
|||
---|---|---|---|
Вызов Callback из C-библиотеки |
|||
#18+
VSVLAD+ в шарповском варианте, у делегата есть параметр: Код: vbnet 1.
а у вас без параметров: Код: vbnet 1.
Да я в курсе. Но тот первый вариант вызывает немедленный краш приложения (и в VB6 и в .Net), и автор "шарповского кода", прописав эту хрень нигде в своем примере этим не пользуется, а тупо висит на потоке через GetMessage с ненулевым таймаутом. а вот мой вариант как раз делает то что надо (я его когда то вымучил еще в VB6). А надо: 1) вернуть 1 2) инициировать процедуру из которой вызовем GetMessage и воспользуемся результатом. Само сообщение берется по любому через GetMessage а не из CallBack, это не противоречит документации. Проблема с .Net-овским таймером, но вот с таймером ли. ... |
|||
:
Нравится:
Не нравится:
|
|||
|
29.01.2017, 23:08
|
|||
---|---|---|---|
Вызов Callback из C-библиотеки |
|||
#18+
Ну правильно, если заменить Код: vbnet 1. 2. 3. 4. 5.
на Код: vbnet 1. 2. 3. 4. 5. 6.
то оно на втором или третьем "message" (а первый-то проходит) начинает стрелять известную ошибку: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления 'frm1' не из того потока, в котором он был создан. (в первом варианте с .Net-контролом не стреляет, но и не тикает) Т.е. предположение что MyMessageAvailable стреляет в хз каких потоках верное, но ток. как лечить. Invoke пробовал втыкать, но оно виснет мертво, видимо неправильно. А в VB6 то в свой поток всегда стреляло, не догоняю пока. ... |
|||
:
Нравится:
Не нравится:
|
|||
|
30.01.2017, 02:33
|
|||
---|---|---|---|
Вызов Callback из C-библиотеки |
|||
#18+
Не, ну здесь вариант из CallBack запостить сообщение в процедуру окна да хоть бы тот же фиктивный WM_TIMER, а оттуда тягать сообщения. Но именно PostMessage а не SendMessage, чтоб не ждать результата, иначе они друг друга закусят и висяк. Идея та же, зато работает. 'CallBack - неважно в каком потоке вызван Код: vbnet 1. 2. 3. 4.
где hForm1 - Код: vbnet 1. 2. 3. 4. 5. 6.
Form1.handle засовывать в CallBack не прокатит Ну и обработка в своем основном потоке: Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22.
Ну там все одно между Callback и взятием сообщения миллисекунд 15 пройдет (если дебажить). Я вот только думаю, может ли случиться, что PostMessage сработало, основной поток поймал WM_TIMER и ничего там не нашел, потому что CallBack еще не вернул 1. ... |
|||
:
Нравится:
Не нравится:
|
|||
|
|
start [/forum/topic.php?fid=20&mobile=1&tid=1400078]: |
0ms |
get settings: |
8ms |
get forum list: |
16ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
41ms |
get topic data: |
13ms |
get forum data: |
3ms |
get page messages: |
50ms |
get tp. blocked users: |
1ms |
others: | 281ms |
total: | 421ms |
0 / 0 |