На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Обязательно выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.

Этот раздел предназначен для вопросов, посвященных разработке компонентов, а также для тестирования собственных бесплатных компонентов с открытым исходным кодом.

Здесь запрещается:
1. Размещать ссылки на какие-либо коммерческие компоненты, реализующие требуемую функциональность.
2. Обсуждать и тестировать коммерческие компоненты или компоненты с закрытым кодом.
3. Давать ссылки на сайты с исходным кодом компонентов. Все тестируемые исходные коды должы быть размещены на сайте ИСХОДНИКИ.RU.
Модераторы: Rouse_, DimaBr
Страницы: (3) [1] 2 3  все  ( Перейти к последнему сообщению )  
> Как вызвать событие? , Есть поток из него надо вызвать событие
    Пишу свой сокет.
    Для приема данных использую поток
    И появилась такая проблема.
    как вызвать событие что пришли данные из потока?
      примерно вот так

      ExpandedWrap disabled
         TmyClass = class(...)
          private
            { Private declarations }
         
            ...
            // Объявление события.
            FOnReceiveData: TNotifyEvent;
         
          published
            { Published declarations }
            ...
            // Публикация события.
            property ReceiveData: TNotifyEvent read FOnReceiveData write FOnReceiveData;
         
         
         
        Function TmyClass.ReceiveData : Integer;
        ...
        begin
          ...
          // Получаем  данные.
          ...
          // Возбуждение события.
          if (Assigned(FOnReceiveData) then FOnReceiveData(self);
      Сообщение отредактировано: VahaC -
        нет ты не понял
        в компоненте есть сокет и есть поток который работает с сокетом на прием данных
        и сделать так когда поток получил данные надо создать событие
        вот смотри код
        код
        ExpandedWrap disabled
          unit CUDPSocket;
           
          interface
           
          uses
            SysUtils,Classes,WinSock,Windows;
           
          const
            MAX_UDPBUF_SIZE =65507;
           
          type
            RecThread = class(TThread)
            public
              RecSocket : TSocket;
              ReadSize : longint;
              status : longint;
            private
              WSAData : TWSAData;
              procedure recvdata(sock:TSocket);
            protected
              procedure Execute; override;
            end;
           
            vmUDPSocket = class(TComponent)
            private
              SActive : boolean;
              SPort : longint;
              SBufSize : longint;
              WSAData : TWSAData;
              UDPSock : TSocket;
              ToAddr : TSockAddr;
              FromAddr : TSockAddr;
              RecTh : RecThread;
              EventRead : TNotifyEvent;
              procedure OnMsgRead();
            protected
            public
              procedure Startup;
              procedure Cleanup;
            published
              property Active : boolean read sActive write sActive;
              property Port : integer read SPort write SPort;
              property BufferSize : longint read SBufSize write SBufSize;
              property OnRead : TNotifyEvent read EventRead write EventRead;
            end;
           
          procedure Register;
           
          implementation
           
          procedure Register;
          begin
            RegisterComponents('Internet', [vmUDPSocket]);
          end;
           
          procedure RecThread.recvdata(sock:TSocket);
          var
            buf : array [1..65507] of char;
            res : string;
            r : integer;
          begin
            r :=recv(sock, buf,ReadSize, 0);
            res:=res+copy(buf,1,r);
            if res<>'' then //вот здесь надо вызвать событие
          end;
           
          procedure RecThread.Execute;
          begin
            WSAStartup($0101,WSAData);
            while true do
              begin
                sleep(50);
                recvdata(RecSocket);
              end;
            WSACleanup;
          end;
           
          procedure vmUDPSocket.Startup;
          begin
            WSAStartup($0101,WSAdata);
            ToAddr.sin_family:=PF_INET;
            ToAddr.sin_addr.S_addr:=inet_addr('127.0.0.1');
            ToAddr.sin_port:=htons(12345);
            UDPSock:=socket(PF_INET,SOCK_DGRAM,0);
            Bind(UDPSock,toaddr,sizeof(toaddr));
            RecTh:=RecThread.Create(true);  RecTh.RecSocket:=UDPSock;  RecTh.Priority:=tpLower;  RecTh.FreeOnTerminate:=true;  RecTh.Resume;
          end;
           
          Procedure vmUDPSocket.Cleanup;
          begin
            RecTh.Terminate;
            closesocket(UDPSock);
            WSACleanup;
          end;
           
          procedure vmUDPSocket.OnMsgRead();
          begin
            if Assigned(eventread) then EventRead(Self);
          end;
           
          end.
        Сообщение отредактировано: v1m -
          v1m, а что мешает делать так:

          ExpandedWrap disabled
            ...
              if res <> '' then
                if (assigned(fOnReceiveData) then fOnReceiveData(self);
            ...
            ExpandedWrap disabled
              ...
                if (res <> '') and (assigned(EventRead) then EventRead(self);
              ...

            Цитата
            [Error] CUDPSocket.pas(64): Undeclared identifier: 'eventread'
              Цитата v1m @
              [Error] CUDPSocket.pas(64): Undeclared identifier: 'eventread'

              и в чем проблема ... переменную нужно определить прежде чем с ней работать ... ;)
                Цитата v1m @
                вот смотри код
                код
                ExpandedWrap disabled
                  unit CUDPSocket;
                   
                  interface
                   
                  uses
                    SysUtils,Classes,WinSock,Windows;
                   
                  const
                    MAX_UDPBUF_SIZE =65507;
                   
                  type
                    RecThread = class(TThread)
                    public
                      RecSocket : TSocket;
                      ReadSize : longint;
                      status : longint;
                    private
                      WSAData : TWSAData;
                      procedure recvdata(sock:TSocket);
                    protected
                      procedure Execute; override;
                    end;
                   
                    vmUDPSocket = class(TComponent)
                    private
                      SActive : boolean;
                      SPort : longint;
                      SBufSize : longint;
                      WSAData : TWSAData;
                      UDPSock : TSocket;
                      ToAddr : TSockAddr;
                      FromAddr : TSockAddr;
                      RecTh : RecThread;
                      EventRead : TNotifyEvent;
                      procedure OnMsgRead();
                    protected
                    public
                      procedure Startup;
                      procedure Cleanup;
                    published
                      property Active : boolean read sActive write sActive;
                      property Port : integer read SPort write SPort;
                      property BufferSize : longint read SBufSize write SBufSize;
                      property OnRead : TNotifyEvent read EventRead write EventRead;
                    end;
                   
                  procedure Register;
                   
                  implementation
                   
                  procedure Register;
                  begin
                    RegisterComponents('Internet', [vmUDPSocket]);
                  end;
                   
                  procedure RecThread.recvdata(sock:TSocket);
                  var
                    buf : array [1..65507] of char;
                    res : string;
                    r : integer;
                  begin
                    r :=recv(sock, buf,ReadSize, 0);
                    res:=res+copy(buf,1,r);
                    if res<>'' then //вот здесь надо вызвать событие
                  end;
                   
                  procedure RecThread.Execute;
                  begin
                    WSAStartup($0101,WSAData);
                    while true do
                      begin
                        sleep(50);
                        recvdata(RecSocket);
                      end;
                    WSACleanup;
                  end;
                   
                  procedure vmUDPSocket.Startup;
                  begin
                    WSAStartup($0101,WSAdata);
                    ToAddr.sin_family:=PF_INET;
                    ToAddr.sin_addr.S_addr:=inet_addr('127.0.0.1');
                    ToAddr.sin_port:=htons(12345);
                    UDPSock:=socket(PF_INET,SOCK_DGRAM,0);
                    Bind(UDPSock,toaddr,sizeof(toaddr));
                    RecTh:=RecThread.Create(true);  RecTh.RecSocket:=UDPSock;  RecTh.Priority:=tpLower;  RecTh.FreeOnTerminate:=true;  RecTh.Resume;
                  end;
                   
                  Procedure vmUDPSocket.Cleanup;
                  begin
                    RecTh.Terminate;
                    closesocket(UDPSock);
                    WSACleanup;
                  end;
                   
                  procedure vmUDPSocket.OnMsgRead();
                  begin
                    if Assigned(eventread) then EventRead(Self);
                  end;
                   
                  end.

                :rtfm:
                  Не мешай мух с котлетами, событие ты создал в компоненте, а вызывать его хочешь из потока, делай синхронизацию с основным ;)
                    Цитата Mr. Gonarh @
                    Не мешай мух с котлетами, событие ты создал в компоненте, а вызывать его хочешь из потока, делай синхронизацию с основным ;)

                    Не обязательно: и у того, и у другого подхода есть свои достоинства и недостатки.
                    Конкретное решение нужно принимать исходя из назначения компонента.
                    Так как хочет v1m можно осуществить передав потоку указатель на экземпляр компонента. Типа такого:
                    ExpandedWrap disabled
                      unit CUDPSocket;
                       
                      interface
                       
                      uses
                        SysUtils,Classes,WinSock,Windows;
                       
                      const
                        MAX_UDPBUF_SIZE =65507;
                       
                      type
                        vmUDPSocket = class(TComponent)
                        private
                          SActive : boolean;
                          SPort : longint;
                          SBufSize : longint;
                          WSAData : TWSAData;
                          UDPSock : TSocket;
                          ToAddr : TSockAddr;
                          FromAddr : TSockAddr;
                          RecTh : RecThread;
                          EventRead : TNotifyEvent;
                          procedure OnMsgRead();
                        protected
                        public
                          procedure Startup;
                          procedure Cleanup;
                        published
                          property Active : boolean read sActive write sActive;
                          property Port : integer read SPort write SPort;
                          property BufferSize : longint read SBufSize write SBufSize;
                          property OnRead : TNotifyEvent read EventRead write EventRead;
                        end;
                       
                        RecThread = class(TThread)
                        private
                          WSAData : TWSAData;
                          procedure recvdata(sock:TSocket);
                        protected
                          procedure Execute; override;
                        public
                          RecSocket : TSocket;
                          ReadSize : longint;
                          status : longint;
                          Component: vmUDPSocket;
                          constructor Create(vmSock: vmUDPSocket; CreateSuspended: Boolean = false);
                        end;
                       
                      procedure Register;
                       
                      implementation
                       
                      procedure RecThread.Create(vmSock: vmUDPSocket; CreateSuspended: Boolean);
                      begin
                        Self.Component := vmSock;
                        inherited Create(CreateSuspended);
                      end;
                       
                      procedure RecThread.recvdata(sock:TSocket);
                      var
                        buf : array [1..65507] of char;
                        res : string;
                        r : integer;
                      begin
                        r :=recv(sock, buf,ReadSize, 0);
                        res:=res+copy(buf,1,r);
                        if (res<>'') and Assigned(Self.Component) and Assigned(Self.Component.ReadEvent) then//вот здесь надо вызвать событие
                          Self.Component.ReadEvent(Self.Component);    
                      end;
                       
                      //...
                       
                      procedure vmUDPSocket.Startup;
                      begin
                        WSAStartup($0101,WSAdata);
                        ToAddr.sin_family:=PF_INET;
                        ToAddr.sin_addr.S_addr:=inet_addr('127.0.0.1');
                        ToAddr.sin_port:=htons(12345);
                        UDPSock:=socket(PF_INET,SOCK_DGRAM,0);
                        Bind(UDPSock,toaddr,sizeof(toaddr));
                        RecTh:=RecThread.Create(Self, true);
                       
                        RecTh.RecSocket:=UDPSock;//вот это тоже лучше вынести в параметры конструктора
                       
                        //а это в конструктор или начало Execute()
                        RecTh.Priority:=tpLower;
                        RecTh.FreeOnTerminate:=true;
                       
                        //от этого лучше отказаться вызывая создание потока с CreateSuspended = false
                        RecTh.Resume;
                      end;
                       
                      end.

                    Модель я думаю ясна.
                    Причем, привел в таком виде на основе TNotifyEvent потому что так предложил автор, а на самом деле лучше определить свой тип события с параметром не компонентом, а потоком (примеры см. в Indy).
                      arj спс)) приду домой проверю :D
                      Mr. Gonarh это как делать? я что то непредставляю как это делать :unsure:
                        arj99 как это скомпилить?)
                        ExpandedWrap disabled
                          type
                            vmUDPSocket = class(TComponent)
                            private
                              SActive : boolean;
                              SPort : longint;
                              SBufSize : longint;
                              WSAData : TWSAData;
                              UDPSock : TSocket;
                              ToAddr : TSockAddr;
                              FromAddr : TSockAddr;
                              RecTh : RecThread;
                              EventRead : TNotifyEvent;
                            protected
                            public
                              procedure Startup;
                              procedure Cleanup;
                            published
                              property Active : boolean read sActive write sActive;
                              property Port : integer read SPort write SPort;
                              property BufferSize : longint read SBufSize write SBufSize;
                              property OnRead : TNotifyEvent read EventRead write EventRead;
                            end;
                            RecThread = class(TThread)
                            public
                              RecSocket : TSocket;
                              ReadSize : longint;
                              status : longint;
                              Component : vmUDPSocket;
                            private
                              WSAData : TWSAData;
                              procedure recvdata(sock:TSocket);
                            protected
                              procedure Execute; override;
                            end;
                          Цитата arj99 @
                          Конкретное решение нужно принимать исходя из назначения компонента.

                          :yes:
                          Цитата
                          передав потоку указатель на экземпляр компонента.

                          Сие не есть гуд :no-sad:
                          В коде ошибка
                          ExpandedWrap disabled
                             if (res<>'') and Assigned(Self.Component) and Assigned(Self.Component.ReadEvent) then
                               //вот здесь надо вызвать событие
                                Self.Component.ReadEvent(Self.Component);

                          Событие не ReadEvent, a OnRead
                            Цитата Mr. Gonarh @
                            Не мешай мух с котлетами, событие ты создал в компоненте, а вызывать его хочешь из потока, делай синхронизацию с основным ;)

                            как это сделать???
                                а с компонентом как?)
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (3) [1] 2 3  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0420 ]   [ 16 queries used ]   [ Generated: 1.05.24, 21:08 GMT ]