PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » PureBasic для Windows » Не разъяснит ли многоуважаемый джин на счет очередей сообщений?


Не разъяснит ли многоуважаемый джин на счет очередей сообщений?

Сообщений 1 страница 9 из 9

1

Имею смутное ощущение что очередей сообщений несколько - по каким-то типам или группам сообщений своя очередь.

Например - NetworkServerEvent() и WindowEvent() читают сообщения из разных очередей ?

И еще - в разных потоках могут быть разные очереди одного типа?

Например - в каждом потоке своя очередь сообщений от NetworkServer.
Т.е. в одном потоке нельзя получить событие от сервера созданного в другом потоке?

Не могли бы многоуважаемый Петр и другие мастера структурно разъяснить эту тему в полном (но кратком ) объеме?

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

0

2

SadStar написал(а):

Например - NetworkServerEvent() и WindowEvent() читают сообщения из разных очередей ?

Они возвращают события разных типов.
WindowEvent() - возвращает события окон, а NetworkServerEvent() - события сервера.
Сервер никак не связан с окнами и его можно создать, даже если в программе нет окон.

SadStar написал(а):

И еще - в разных потоках могут быть разные очереди одного типа?

Для окон в каждом потоке своя очередь.

Примечание: Если нужно открыть окно из потока, то для обработки событий этого окна этот же поток должен будет в цикле вызывать WindowEvent() или WaitWindowEvent(), так как события окна не передаются между потоками.

А для сети (сервер, клиент) общая очередь для всех потоков.
В качестве примера, можно посмотреть эту программу Пример WEB-сервера на PureBasic
В ней, сервер создается в основном потоке, а его события обрабатываются в другом потоке.

0

3

Всплыла проблема :( по теме этой темы :)

Ситуация

Есть Функция1 которая
- формирует пакет запроса,
- открывает соединение с заданным IP
- посылает пакет
- ждет ответ (или тайм-аут) = цикл NetworkClientEvent() !!!
- получает пакет ответа
- закрывает соединение
- возвращает полученный пакет

Есть Функция2 которая
- вызывает функцию1 несколько раз с разными параметрами запроса

В однопоточном режиме - все Ок.

Пытаюсь сделать многопоточный режим т.е.
Функция2 запускается одновременно вразных потоках для работы с разными IP одновременно

В XP все работает как задумал.
В 7 и 10 - падает по "Invalid memory access"

Вопрос.
Как правильно организовать цикл опроса NetworkClientEvent() (вместо существующего в Функции1)
имея в виду то, что очередь сетевых сообщений одна на все потоки (см.предыдущее сообщение и др.инфу)
???

0

4

Возможно что-то не так в коде, потому что NetworkClientEvent() нормально работает с несколькими потоками.

0

5

Прошу помощи в анализе кода, т.к. сам понять не могу.
Проблема все та же - в XP=Ok, в Win7=Failed.
Кусок кода получающий ответ по сети - здесь сидит косяк как я думаю исходя из анализа отладочных сообщений
В какой-то момент после десятков или сотен вызовов этой функции в шести потоках она возвращает блок памяти нулевой длины!!!
*Pack - ссылка на блок памяти заполенный данными запроса
*Response - ссылка на блок памяти 2048 байт для размещения ответа

Код:
Procedure.l GetSNMPresponse(*Pack, IP$, *Response, *Error.long)
....
....
....
; получить ответ ---------------------------------------------
Protected TimeOut=0
Protected Ok=#False
Repeat
  NetEvent= NetworkClientEvent(Connection)
  If NetEvent= #PB_NetworkEvent_Data
    Result = ReceiveNetworkData(Connection, *DataBuffer, 2048) ; кол.принятых байтов
    SaveBlockSize(IP$, @Result, Result) ; отладка
    If Result = -1	; обрыв связи
      *Error\l=806
      Break
    ElseIf Result=0 ;ловушка ошибки
      *Error\l=805
      MessageRequester("", "ReceiveNetworkData() received 0 byte")
      Break
    EndIf
    *Response=ReAllocateMemory(*Response,Result)
    If Not *Response 
      *Error\l=807
      MessageRequester("", "GetSNMPresponse() failed by ReAllocateMemory(*Response,Result)")
      Break
    EndIf
    CopyMemory(*DataBuffer, *Response, Result)
    Ok=#True
    Break
  EndIf
  ;
  Delay(100) ;mSec
  TimeOut+100
  If TimeOut > 2000 ;timeout 2 sec
    *Error\l=999
    Break
  EndIf
ForEver

  CloseNetworkConnection(Connection)
  FreeMemory(*DataBuffer)
	
 ProcedureReturn Ok
	
EndProcedure

Может вдруг начать косячить в семерке это *Response=ReAllocateMemory(*Response,Result) ?
строка кода Result = ReceiveNetworkData(Connection, *DataBuffer, 2048) ; кол.принятых байтов
всегда возвращает ненулевой результат (по отладочным данным)
А на выходе - блок нулевой длины ???

0

6

Т. е. размер области памяти *Response, 0 байт?

Проблема может быть вот в чем.

Код:
Procedure x(*Response)
  *Response=ReAllocateMemory(*Response,8196)
  Debug "Процедура. Адрес "+*Response+" Размер "+MemorySize(*Response)
EndProcedure

*p = AllocateMemory(1024)
Debug "До вызова процедуры. Адрес "+*p+" Размер "+MemorySize(*p)
x(*p)
Debug "После вызова процедуры. Адрес "+*p

Адрес памяти изменился, но за пределами процедуры он остался прежним.

Нужно передавать указатель на указатель.

Код:
Structure Pointer
  *p
EndStructure

Procedure x(*Response.Pointer)
  *Response\p=ReAllocateMemory(*Response\p,8196)
  Debug "Процедура. Адрес "+*Response\p+" Размер "+MemorySize(*Response\p)
EndProcedure

*p = AllocateMemory(1024)
Debug "До вызова процедуры. Адрес "+*p+" Размер "+MemorySize(*p)
x(@*p)
Debug "После вызова процедуры. Адрес "+*p+" Размер "+MemorySize(*p)

0

7

Да здравствует Петр - великий знаток Пурика и других важных вещей!

Ваше предложение успешно реализовано. Утилита работает без падений в XP, Win7, Win10.

Для полного просветления нужно уяснить несколько моментов.

В частности - ситуация.

Есть переменная Var1.l

Передаем в функцию ее адрес
Func1(@Var1)

Как внутри функции получить значение переменной Var1 ? Вернуть значение в Var1 ?
Procedure Func1(*Var)
    Value=PeekL(*Var) ; ????? получить
    PokeL(*Var, Value2) ; ???? вернуть
endprocedure

0

8

Проверка моего просветления

Код:
OpenConsole()

Procedure ChangeBlockSize(Addr_Of_Addr_Of_Block)
    Protected New_Addr_Of_Block=ReAllocateMemory(PeekL(Addr_Of_Addr_Of_Block), 65536)
         PrintN("-----------------")
         PrintN("PeekL(Addr_Of_Addr_Of_Block)="+Str(PeekL(Addr_Of_Addr_Of_Block))+#CRLF$)
         PrintN("New_Addr_Of_Block="+Str(New_Addr_Of_Block)+#CRLF$)
    PokeL(Addr_Of_Addr_Of_Block,New_Addr_Of_Block)
         PrintN("-----------------")
EndProcedure

Addr_Of_Block=AllocateMemory(1024)
        PrintN(#CRLF$)
        PrintN("Addr_Of_Block="+Str(Addr_Of_Block)+#CRLF$)
        PrintN("MemorySize(Addr_Of_Block)="+Str(MemorySize(Addr_Of_Block))+#CRLF$)
        PrintN("Call ChangeBlockSize(@Addr_Of_Block)"+#CRLF$)
ChangeBlockSize(@Addr_Of_Block)
        PrintN("Addr_Of_Block="+Str(Addr_Of_Block)+#CRLF$)
        PrintN("MemorySize(Addr_Of_Block)="+Str(MemorySize(Addr_Of_Block))+#CRLF$)
Print("Press Enter>")
Input()

0

9

SadStar написал(а):

Как внутри функции получить значение переменной Var1 ? Вернуть значение в Var1 ?

Проще сделать так.

Код:
Procedure Func1(*Var.Long)
  Value=*Var\l ; ????? получить
  *Var\l = Value2 ; ???? вернуть
EndProcedure

Func1(@Var)

Если в переменной указатель, то вместо Long должно быть Integer, иначе будет неправильно работать в x64.

0


Вы здесь » PureBasic - форум » PureBasic для Windows » Не разъяснит ли многоуважаемый джин на счет очередей сообщений?