Hallo zusammen.
Erstmal muss ich sagen, dass Threads usw. mehr oder weniger Neuland für mich sind. Bin deshalb auch für konstruktive Anmerkungen die evtl. etwas off-topic sind, dankbar.
Ich möchte eine USB Kommunikation zwischen PC und einem Gerät aufbauen. Ein Frame besteht jeweils aus Header und den eigentlichen Daten. Dieses Frame wird in zwei Schritten versendet.
Es wird also erst der Header versendet und im zweiten Schritt die Daten. Die Daten dürfen aber erst versendet werden, wenn der Header von Gerät empfangen wurde. Wenn innerhalb eines Timeouts der Header nicht empfangen wurde, soll das Programm in seinen Ursprungszustand zurückkehren. Dies habe ich versucht mit WaitForSingleObject und SetEvent zu erreichen...
Ich habe die den komplette Vorgang für ein Frame einen neuen Thread gepackt:
Delphi-Quellcode:
type
TBulkTransferThread = class(TThread)
private
...
...
protected
public
constructor create( ...
... );
end;
TBulkWriteThread = class(TBulkTransferThread)
protected
procedure CallbackFktWrite(ErrorCode : Longint;
NumberOfBytesTransfered : Longint);
procedure Execute; override;
end;
...
...
Bei der Implementierung erzeuge ich mir ein Event. Mit Hilfe von WaitForSingleObject und diesem Event möchte ich das Warten realisieren:
Delphi-Quellcode:
implementation
uses
SysUtils;
constructor TBulkTransferThread.create( ...
... );
begin
...
...
inherited create(False);
end;
procedure TBulkWriteThread.Execute();
var
bRet : BOOL;
Ret : Integer;
begin
WriteFinished := TEvent.Create(nil,true,false,'myEvent');
WriteFinished.ResetEvent;
// Header versenden
bRet := USBWriteAsync(...
...
@TBulkWriteThread.CallbackFktWrite);
Ret := WaitForSingleObject(Self.WriteFinished.Handle, TIMEOUT_VALUE);
if Ret = WAIT_OBJECT_0 then
Ret := USB_OK
else
Ret := USB_SEND_COMMAND_ERROR;
WriteFinished.ResetEvent;
if (Ret = USB_OK) and (USBcb.nDATA > 0) then
// Daten versenden
bRet := USBWriteAsync(...
...
@TBulkWriteThread.CallbackFktWrite);
if (Ret = USB_OK) and (USBcb.nDATA > 0) then
Ret := WaitForSingleObject(Self.WriteFinished.Handle, TIMEOUT_VALUE);
WriteFinished.Destroy;
if Ret = WAIT_OBJECT_0 then
Integer(Status^) := USB_OK
else
Integer(Status^) := USB_SEND_COMMAND_ERROR;
end;
In der Callback-Funktion der Senderoutine, welche ausgeführt wird sobald die Daten versendet wurden, wird das Event gesetzt:
Delphi-Quellcode:
Procedure TBulkWriteThread.CallbackFktWrite(ErrorCode : Longint; NumberOfBytesTransfered : Longint);
begin
if ErrorCode <> 0
then
begin
ErrorCode := GetLastError();
MessageDlg('
Error#: ' + IntToStr(ErrorCode), mtError, [mbOk], 0);
end;
SetEvent(Self.WriteFinished.Handle);
// <-- Hier access violation!!
end;
Soweit, so gut. Der Header wird versendet, kommt beim Gerät an und die Callback-Funktion wird aufgerufen.
Allerdings tritt bei SetEvent eine
access violation auf:
'In Porjekt ... trat ein Problem mit folgender Meldung auf: '
access violation at 0x0046b567: read of address 0x00000060'. Prozess angehalten'
Ich bekomme nicht heraus, was ich falsch gemacht habe. Wer kann mir da helfen?
Vielen Dank