AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Zugriffsverletzung bei(Kommunikations)Timeout mit overlapped
Thema durchsuchen
Ansicht
Themen-Optionen

Zugriffsverletzung bei(Kommunikations)Timeout mit overlapped

Ein Thema von Viktorii · begonnen am 1. Okt 2007 · letzter Beitrag vom 8. Okt 2007
Antwort Antwort
Viktorii

Registriert seit: 19. Jul 2007
358 Beiträge
 
#1

Zugriffsverletzung bei(Kommunikations)Timeout mit overlapped

  Alt 1. Okt 2007, 12:06
Moin zusammen.

Ich möchte von einem USB-Geräte lesen und es beschreiben können. Dazu benutze ich DriverX von Tetradyne. Das funktioniert soweit auch alles wunderbar.
Wenn ich nun vom Gerät lesen möchte, dieses aber nicht antwortet bleibt meine Anwendung in der Read Funktion 'stecken'. Ich möchte also sowas wie ein Timeout haben. Der Treiber bietet keine Möglichkeit einen Timeout einzustellen. Die einzige Chance die ich sehe ist es mit 'overlapped' zu realisieren. 'Overlapped' war mit bis jetzt noch kein Begriff. Die Dokumentation gibt leider nicht viel her:

Zitat:
Reads from a USB device bulk endpoint.


BOOL DXUSBAPI UsbBulkRead(PDXUSB_DEVICE device, ULONG iIndex, ULONG endpoint, ULONG flags, PVOID buffer, ULONG cb, PULONG pcbRet, LPOVERLAPPED pol);

Parameters

...

pol

Pointer to initialized OVERLAPPED structure to use for request or NULL to block on completion.

...

Comments
If pol is NULL, UsbBulkRead will block on completion of the request. If pol is not NULL, then UsbBulkRead will return immediately. The caller can then block on completion of the request using the specified OVERLAPPED structure and the Win32 WaitForSingleObject or GetOverlappedResult APIs.

Nun habe ich ein wenig rumgegooglet und habe versucht, das was ich gefunden habe umzusetzten:


Code:
procedure InitOverlapped(var Overlapped : lpOverlapped);
begin
  Overlapped.Offset := 0;
  Overlapped.OffsetHigh := 0;
  Overlapped.Internal := 0;
  Overlapped.InternalHigh := 0;}
  Overlapped.hEvent := CreateEvent(nil,True,False,'');
end;


function ReceiveCommand(...):..
var
  ...
  Overlapped     : lpOverlapped;

begin

  InitOverlapped(Overlapped);

  Ret := UsbBulkRead(deviceHandle, 0, 0, 0, @USBcb, 8, BytesReceived, Overlapped);
Wenn ich nun aber das Programm ausführe und auf ein Element der Overlapped Struktur zugegriffen wird, kommt es zu einer Zugriffsverletzung:

Zitat:
Im Projekt xyz.exe ist eine Exception der Klasse EaccessViolation mit der Meldung 'Zugriffsverletzung bei Adresse 00464ED1 in Modul xyz.exe'. Schreiben von Adresse 00431a20' aufgetreten.
Kann dies nicht wirklich nachvollziehen und habe auch keine hilfreichen Informationen ergooglen können.

Wer kann bei mir für Aufklärung sorgen?

Vielen Dank für jegliche Hinweise und Hilfe!
  Mit Zitat antworten Zitat
Robert Marquardt
(Gast)

n/a Beiträge
 
#2

Re: Zugriffsverletzung bei(Kommunikations)Timeout mit overla

  Alt 1. Okt 2007, 12:26
Das ist die uebliche Verwechslung von Pointer auf Struktur und Struktur.

Delphi-Quellcode:
procedure InitOverlapped(var Overlapped: TOverlapped);
begin
  Overlapped.Offset := 0;
  Overlapped.OffsetHigh := 0;
  Overlapped.Internal := 0;
  Overlapped.InternalHigh := 0;
  Overlapped.hEvent := CreateEvent(nil,True,False,'');
end;
Der Eventname ist verdaechtig ein anonymer Event verwendet nil statt ''.
Ist ein ManualReset-Event noetig?

Hier setzt sich der Fehler fort.
Delphi-Quellcode:
function ReceiveCommand(...):..
var
  ...
  Overlapped: TOverlapped;
begin
  InitOverlapped(Overlapped);
  Ret := UsbBulkRead(deviceHandle, 0, 0, 0, @USBcb, 8, BytesReceived, @Overlapped);
Wird denn nach UsbBulkRead auf den Event gewartet? Wenn nicht wird die Funktion verlassen und Overlapped wird zerstoert. Es muss sichergestellt werden das Overlapped solange existiert bis UsbBulkRead den Event nicht mehr triggert.
  Mit Zitat antworten Zitat
Viktorii

Registriert seit: 19. Jul 2007
358 Beiträge
 
#3

Re: Zugriffsverletzung bei(Kommunikations)Timeout mit overla

  Alt 1. Okt 2007, 14:00
Erstmal vielen Dank für die schnelle Antwort.

Zitat von Robert Marquardt:
Das ist die uebliche Verwechslung von Pointer auf Struktur und Struktur.
Verstehe das nicht genau. Was genau bedeute Verwechslung?

Zitat von Robert Marquardt:
Delphi-Quellcode:
procedure InitOverlapped(var Overlapped: TOverlapped);
begin
  Overlapped.Offset := 0;
  Overlapped.OffsetHigh := 0;
  Overlapped.Internal := 0;
  Overlapped.InternalHigh := 0;
  Overlapped.hEvent := CreateEvent(nil,True,False,'');
end;
Der Eventname ist verdaechtig ein anonymer Event verwendet nil statt ''.
Ist ein ManualReset-Event noetig?
Ich muss zugeben, dass ich mich damit noch nicht auseinandergesetzt habe, weil die Zugriffsverletzung schon bei 'Overlapped.Offset := 0;' auftritt. Habe dieses Codesegment so im Netz gefunden. Hab es erstmal so übernommen. Wie schon angedeutet, bin ich mit sowas noch nicht in Berührung gekommen. Leider hilft die Delphi Hilfe da auch nicht weiter

Zitat von Robert Marquardt:
Hier setzt sich der Fehler fort.
Delphi-Quellcode:
function ReceiveCommand(...):..
var
  ...
  Overlapped: TOverlapped;
begin
  InitOverlapped(Overlapped);
  Ret := UsbBulkRead(deviceHandle, 0, 0, 0, @USBcb, 8, BytesReceived, @Overlapped);
Wird denn nach UsbBulkRead auf den Event gewartet? Wenn nicht wird die Funktion verlassen und Overlapped wird zerstoert. Es muss sichergestellt werden das Overlapped solange existiert bis UsbBulkRead den Event nicht mehr triggert.
Also mein Ansatz sollte folgender sein: Soweit ich das verstanden habe, wird die Funktion (UsbBulkRead) sofort wieder verlassen, wenn ich das Overlapped verwende. Nun möchte ich eine gewisse (Timeout-) Zeit nach dem Lesen warten und dann schauen ob gelesen wurde oder nicht. Ist das so zu realisieren oder habe ich da was falsch verstanden?

Nochmals vielen Dank!
  Mit Zitat antworten Zitat
Robert Marquardt
(Gast)

n/a Beiträge
 
#4

Re: Zugriffsverletzung bei(Kommunikations)Timeout mit overla

  Alt 1. Okt 2007, 18:36
LPOVERLAPPED ist in C ein "OVERLAPPED *", also ein Zeiger auf ein OVERLAPPED-Record. In Delphi gibt es OVERLAPPED als TOverlapped bereits. LPOVERLAPPED waere dann "type LPOVERLAPPED = ^TOverlapped;". Damit hast du nie ein Record deklariert und die Variable Overlapped ist ein uninitialisierter Zeiger und zeigt in den Wald. Natuerlich bekommst du damit eine Schutzverletzung.

Das mit dem warten ob etwas gelesen wurde, sollte sich realisieren lassen. SleepEx sollte genuegen. Es muss allerdings danach das UsbBulkRead (vermutlich mit CancelIo) abgebrochen werden, falls SleepEx den Timeout signalisiert. Korrektur: WaitForSingleObject.
Besser ist allerdings du schreibst einen Thread der das handhabt. Noch besser du findest jemanden der mit solchen Sachen vertraut ist. Ich bin es, aber ich habe keine Zeit.
  Mit Zitat antworten Zitat
Viktorii

Registriert seit: 19. Jul 2007
358 Beiträge
 
#5

Re: Zugriffsverletzung bei(Kommunikations)Timeout mit overla

  Alt 2. Okt 2007, 12:05
Zitat:
LPOVERLAPPED ist in C ein "OVERLAPPED *", also ein Zeiger auf ein OVERLAPPED-Record. In Delphi gibt es OVERLAPPED als TOverlapped bereits. LPOVERLAPPED waere dann "type LPOVERLAPPED = ^TOverlapped;". Damit hast du nie ein Record deklariert und die Variable Overlapped ist ein uninitialisierter Zeiger und zeigt in den Wald. Natuerlich bekommst du damit eine Schutzverletzung.
Achsooooo.... LP steht für long pointer. Naja, wenn da lp anstatt LP gestanden hätte, wäre ich vielleicht sogar selber drauf gekommen.

Zitat:
Das mit dem warten ob etwas gelesen wurde, sollte sich realisieren lassen. SleepEx sollte genuegen. Es muss allerdings danach das UsbBulkRead (vermutlich mit CancelIo) abgebrochen werden, falls SleepEx den Timeout signalisiert. Korrektur: WaitForSingleObject.
Besser ist allerdings du schreibst einen Thread der das handhabt.
Ansonsten funktioniert mittlerweile die 'unelegantere' Lösung ohne einen neuen Thread fast. Da ich mit Thread Programmierung bis jetzt noch nicht wirklich in Berührung gekommen bin, möchte ich das Problem erstmal so lösen, bevor ich mich mit Threads wirklich auseinander setze.

Die jetzige Lösung funktioniert in sofern, dass die UsbBulkRead-Funktion sofort wieder verlassen wird und die Applikation solange an WaitForSingleObject wartet bis die Daten empfangen wurden bzw. der Timeout erreicht wurde. Werden die Daten gesendet, werden diese auch korrekt empfangen. Werden keine Daten gesendet und somit der Timeout erreicht, kann ich das am Rückgabewerte sehen. Soweit, so gut.

Nur das Abbrechen der UsbBulkRead Funktion mit CancelIO scheint nicht zu klappen. Der Rückgabewert ist FALSE. Mit GetLastError bekomme ich den Rückgabewert 6. Das bringt mich zu einer vielleicht etwas dummen Frage: Gibt es für Delphi irgendwo die defines bzw. 'Konstantenzuweisungen' für die Rückgabewerte? Habe bei WaitForSingleObject beispielsweise gesehen, dass WAIT_TIMEOUT = 258 sein müsste und 0 scheint wohl WAIT_OBJECT_0 zu sein. Bei C hat gibt es ja meistens Header Dateien, in denen die defines/macros für die Rückgabewerte eingetragen sind.

Leider bin ich mit diesen (Windows API ?) Funktionen auch noch nicht so vertraut. Woran könnte es liegen, dass es mit CancelIO nicht funktioniert? Ist es sicher, dass UsbBulkRead wie andere I/O Funktionen abgebrochen werden muss?

Zur Vollständigkeit, so sieht es im Moment bei mir aus (zwei mal Read, das Zweite mal nur wenn das Erste erfolgreich war):

Delphi-Quellcode:
procedure InitOverlapped(var Overlapped : lpOverlapped);
begin
  Overlapped.Offset := 0;
  Overlapped.OffsetHigh := 0;
  Overlapped.Internal := 0;
  Overlapped.InternalHigh := 0;
  Overlapped.hEvent := CreateEvent(nil,False,False,nil);
end;


function ReceiveCommand(...):Integer;
var
  ...
  lpUSBOverlapped : lpOverlapped;
  USBOverlapped : TOverlapped;

begin
  lpUSBOverlapped := @USBOverlapped;

  InitOverlapped(lpUSBOverlapped);

  bRet := UsbBulkRead(deviceHandle, 0, 0, 0, @USBcb, HEADERSIZE, BytesReceived, lpUSBOverlapped);

  Ret := WaitForSingleObject(USBOverlapped.hEvent, TIMEOUT_VALUE);

  if (Ret = 0) and (USBOverlapped.InternalHigh = HEADERSIZE) then
  begin
    bRet := UsbBulkRead(deviceHandle, 0, 0, 0, Data, USBcb.nDATA, BytesReceived, lpUSBOverlapped);
    Ret := WaitForSingleObject(USBOverlapped.hEvent, TIMEOUT_VALUE);
  end
  else
  if Ret = 258 then
     bRet := CancelIO(USBOverlapped.hEvent);


  if (Ret = 0) and (USBOverlapped.InternalHigh = USBcb.nDATA) then
  begin
    ...
  end
  else
  begin
    Result := USB_RECEIVE_COMMAND_ERROR;
    if Ret = 258 then
      bRet := CancelIO(USBOverlapped.hEvent);
  end;
              
end;
Kann mir jemand Literatur zu Grundlagen für Thread- und API-Programmierung empfehlen? Habe bis jetzt das hier gefunden:

http://www.michael-puff.de/Developer...mit_Delphi.pdf
http://www.michael-puff.de/Developer...orials_pdf.pdf

Werde mich auf jeden Fall damit auseinander setzen.

Vielen Dank für Deine Geduld!
  Mit Zitat antworten Zitat
Robert Marquardt
(Gast)

n/a Beiträge
 
#6

Re: Zugriffsverletzung bei(Kommunikations)Timeout mit overla

  Alt 2. Okt 2007, 15:55
Studier mal meine HID-Komponente. In der JVCL oder http://www.soft-gems.net
Dort wird ein Daten-Event mit einem Thread implementiert. Ist allerdings trickreich und fast undokumentiert.
Bei USB Bulk Reads ist uebrigens eine das performante Lesen wirklich trickreich, da man immer mehrere overlapped Reads ausstehen haben muss. Ich weiss nicht inwieweit die DLL dich da unterstuetzt.
  Mit Zitat antworten Zitat
Viktorii

Registriert seit: 19. Jul 2007
358 Beiträge
 
#7

Re: Zugriffsverletzung bei(Kommunikations)Timeout mit overla

  Alt 4. Okt 2007, 15:06
Zwei Fragen habe ich noch:
1. Also, die HID Komponente ist doch sehr komplex und hilft mir nicht wirklich weiter. Nachdem ich mich jetzt in das Thema Threads am einarbeiten bin, würde ich folgenden Ansatz versuchen:

Ich verpacke einen Lesevorgang in einen separaten Thread:

Delphi-Quellcode:
  bRet := UsbBulkRead(deviceHandle, 0, 0, 0, @USBcb, HEADERSIZE, BytesReceived, lpUSBOverlapped);

  Ret := WaitForSingleObject(USBOverlapped.hEvent, TIMEOUT_VALUE);
Wenn Daten empfangen werden, wird ein Event ausgelöst und der Thread beendet sich. Werden keine Daten empfangen, läuft der Timeout ab und der Thread beendet sich auch. Muss ich in diesem Fall die UsbBulkRead Funktion nicht mehr abbrechen, weil der Thread dann nicht mehr exisitiert? Wäre das so der richtige Ansatz?

2. Die Geschichte mit den Rückgabewerten stört mich immer noch. Beispielsweise der Rückgabewert 6 von GetLastError, wie oben erwähnt. Gibt es eine Möglichkeit herauszufinden, was das genau bedeutet? Finde es auch unelegant die Rückgabewert als 'Magic Values', beispielsweise auf 44 zu prüfen, anstatt auf XYZ_ERROR....

Nochmals vielen Dank.
  Mit Zitat antworten Zitat
Robert Marquardt
(Gast)

n/a Beiträge
 
#8

Re: Zugriffsverletzung bei(Kommunikations)Timeout mit overla

  Alt 4. Okt 2007, 15:21
Ich gebe auf. erstens fuehle ich mich gerade mal wieder ziemlich schlecht und zweitens fehlt dir offensichtlich zu viel an Grundlagen.
Kann jemand anders uebernehmen?
  Mit Zitat antworten Zitat
Viktorii

Registriert seit: 19. Jul 2007
358 Beiträge
 
#9

Re: Zugriffsverletzung bei(Kommunikations)Timeout mit overla

  Alt 5. Okt 2007, 08:20
Zitat von Robert Marquardt:
Ich gebe auf. erstens fuehle ich mich gerade mal wieder ziemlich schlecht
Das tut mir leid.


Zitat von Robert Marquardt:
und zweitens fehlt dir offensichtlich zu viel an Grundlagen.
Die versuche ich mir ja gerade anzueignen, wie ich weiter oben ja schon gepostet habe. Jeder hat ja mal angefangen.


Zitat von Robert Marquardt:
Kann jemand anders uebernehmen?
Würde sich dann vielleicht noch jemand erbarmen, einem armen wissbegierigen Delphi Neuling ein kleines bisschen unter die Arme zu greifen

Ich bedanke mich schon mal im Voraus
  Mit Zitat antworten Zitat
Viktorii

Registriert seit: 19. Jul 2007
358 Beiträge
 
#10

Re: Zugriffsverletzung bei(Kommunikations)Timeout mit overla

  Alt 8. Okt 2007, 08:46
Kann mir da niemand weiterhelfen? Wäre sehr wichtig für mich
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:47 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz