Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.145.2.184] |
|
Страницы: (3) [1] 2 3 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Пишу свой сокет.
Для приема данных использую поток И появилась такая проблема. как вызвать событие что пришли данные из потока? |
Сообщ.
#2
,
|
|
|
примерно вот так
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); |
Сообщ.
#3
,
|
|
|
нет ты не понял
в компоненте есть сокет и есть поток который работает с сокетом на прием данных и сделать так когда поток получил данные надо создать событие вот смотри код код 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. |
Сообщ.
#4
,
|
|
|
v1m, а что мешает делать так:
... if res <> '' then if (assigned(fOnReceiveData) then fOnReceiveData(self); ... |
Сообщ.
#5
,
|
|
|
... if (res <> '') and (assigned(EventRead) then EventRead(self); ... Цитата [Error] CUDPSocket.pas(64): Undeclared identifier: 'eventread' |
Сообщ.
#6
,
|
|
|
Цитата v1m @ [Error] CUDPSocket.pas(64): Undeclared identifier: 'eventread' и в чем проблема ... переменную нужно определить прежде чем с ней работать ... |
Сообщ.
#7
,
|
|
|
Цитата v1m @ вот смотри код код 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. |
Сообщ.
#8
,
|
|
|
Не мешай мух с котлетами, событие ты создал в компоненте, а вызывать его хочешь из потока, делай синхронизацию с основным
|
Сообщ.
#9
,
|
|
|
Цитата Mr. Gonarh @ Не мешай мух с котлетами, событие ты создал в компоненте, а вызывать его хочешь из потока, делай синхронизацию с основным Не обязательно: и у того, и у другого подхода есть свои достоинства и недостатки. Конкретное решение нужно принимать исходя из назначения компонента. Так как хочет v1m можно осуществить передав потоку указатель на экземпляр компонента. Типа такого: 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). |
Сообщ.
#10
,
|
|
|
arj спс)) приду домой проверю
Mr. Gonarh это как делать? я что то непредставляю как это делать |
Сообщ.
#11
,
|
|
|
arj99 как это скомпилить?)
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; |
Сообщ.
#12
,
|
|
|
Цитата arj99 @ Конкретное решение нужно принимать исходя из назначения компонента. Цитата передав потоку указатель на экземпляр компонента. Сие не есть гуд В коде ошибка if (res<>'') and Assigned(Self.Component) and Assigned(Self.Component.ReadEvent) then //вот здесь надо вызвать событие Self.Component.ReadEvent(Self.Component); Событие не ReadEvent, a OnRead |
Сообщ.
#13
,
|
|
|
Цитата Mr. Gonarh @ Не мешай мух с котлетами, событие ты создал в компоненте, а вызывать его хочешь из потока, делай синхронизацию с основным как это сделать??? |
Сообщ.
#14
,
|
|
|
Сообщ.
#15
,
|
|
|
а с компонентом как?)
|