Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Problem mit Threads (https://www.delphipraxis.net/85263-problem-mit-threads.html)

Nils_13 28. Jan 2007 10:50


Problem mit Threads
 
Hi,
Dieser Code funktioniert nicht:
cthread := BeginThread(nil, 0, @OpenURL, PChar(urls[0]), 0, ThreadId); // urls = TDynStrArray

Dieser Code funkioniert:
cthread := BeginThread(nil, 0, @OpenURL, PChar('http://stream.clubnation.fm'), 0, ThreadId);

In urls[0] steht http://stream.clubnation.fm.

Warum funktioniert der zweite Code, aber der benötigte erste Code nicht ?
In OpenURL werden die korrekten Parameter übergeben (http://stream.clubnation.fm).

ste_ett 28. Jan 2007 11:11

Re: Problem mit Threads
 
Was funktioniert nicht?

Wird der Thread nict erstellt?
Die Prozedur nicht aufgerufen?

Nils_13 28. Jan 2007 11:24

Re: Problem mit Threads
 
Er meint, er könnte den Stream nicht abspielen, im anderen Fall spielt er ihn ab.

alzaimar 28. Jan 2007 11:44

Re: Problem mit Threads
 
Was genau ist den "urls[0]"? Wirklich ein String? oder vielleicht doch ein Zeiger auf einen String? Typecasting mit PChar ist ein häufiger Stolperstein. Abhilfe: Du lagerst das Beginthread in eine Prozedur aus, die einen Parameter (nämlich die URL) enthält. diesen Parameter kannst Du dann in ein PChar casten, ohne Dir Sorgen zu machen.

Delphi-Quellcode:
Function StartPlayStream (anURL : String) : THandle;
Begin
  Result := BeginThread(nil, 0, @OpenURL, PChar(anURL), 0, ThreadId); // urls = TDynStrArray
End;
Ich habe ein ähnliches Problem mit 'OutputDebugString' gehabt und mir dann so eine (ziemliche dumme) Hilfsroutine geschrieben.

Nils_13 28. Jan 2007 12:22

Re: Problem mit Threads
 
Urls ist ein Array of String.
Delphi-Quellcode:
function TfrmMain.StartPlayStream(anURL : String) : THandle;
var ThreadId : Cardinal;
begin
  Result := BeginThread(nil, 0, @OpenURL, PChar(anURL), 0, ThreadId); // urls = TDynStrArray
end;

procedure TfrmMain.lvDblClick(Sender: TObject);
var s : String;
begin
  s := urls[0];
  cthread := StartPlayStream(s);
end;
Zitat:

---------------------------
Fehler
---------------------------
Can't play the stream

(error code: 0)
---------------------------
OK
---------------------------

ste_ett 28. Jan 2007 15:08

Re: Problem mit Threads
 
Zeig uns am Besten auch noch OpenURL. :)

Ich tippe mal auf ein "nil" als Parameter innerhalb der Funktion, da der String nur eine lokale Variable ist oder du das "stdcall" vergessen hast. :)

Entweder eine globale Variable (naja, nicht wirklich eine Alternative, nur der Möglichkeit halben genannt) oder Speicher reservieren für PChar. :)

Nils_13 28. Jan 2007 15:25

Re: Problem mit Threads
 
Irgendwie scheint heute nicht mein Tag zu sein... Bittesehr:
Delphi-Quellcode:
function OpenURL(url: PChar) : Integer;
var
  icy: PChar;
  Len, Progress: DWORD;
begin
  Result := 0;
  BASS_StreamFree(chan); // Alten Stream beenden
  progress := 0;
  SendMessage(win, WM_INFO_UPDATE, 0, 0);

  chan := BASS_StreamCreateURL(url, 0, BASS_STREAM_STATUS, @StatusProc, 0);
  if (chan = 0) then
  begin
    SendMessage(win, WM_INFO_UPDATE, 1, 0); // Fehler
  end else
  begin
    // Progress
    repeat
      len := BASS_StreamGetFilePosition(chan, BASS_FILEPOS_END);
      if (len = DW_Error) then
        Break; // Fehler
      progress := (BASS_StreamGetFilePosition(chan, BASS_FILEPOS_DOWNLOAD) -
        BASS_StreamGetFilePosition(chan, BASS_FILEPOS_CURRENT)) * 100 div len;
      // Buffer Prozent
      SendMessage(win, WM_INFO_UPDATE, 2, progress);

    until
      progress > 75;

    // Name + Bitrate
    icy := BASS_ChannelGetTags(chan, BASS_TAG_ICY);
    if (icy <> nil) then
      while (icy^ <> #0) do
      begin
        if (Copy(icy, 1, 9) = 'icy-name:') then
          SendMessage(win, WM_INFO_UPDATE, 3, DWORD(PChar(Copy(icy, 10, MaxInt))))

        else if (Copy(icy, 1, 7) = 'icy-br:') then

          SendMessage(win, WM_INFO_UPDATE, 4, DWORD(PChar('bitrate: ' + Copy(icy, 8, MaxInt))));
        icy := icy + Length(icy) + 1;
      end;
    // Stream-Titel + Sync setzen
    DoMeta(BASS_ChannelGetTags(chan, BASS_TAG_META));
    BASS_ChannelSetSync(chan, BASS_SYNC_META, 0, @MetaSync, 0);
    // Abspielen
    BASS_ChannelPlay(chan, FALSE);
  end;
  cthread := 0;
end;

ste_ett 28. Jan 2007 15:44

Re: Problem mit Threads
 
Bist du mal mit dem Debugger durchgegangen und hast die Variablen und Parameter geprüft?

Robert Marquardt 28. Jan 2007 15:54

Re: Problem mit Threads
 
ste_ett hat das Problem sauber diagnostiziert.
Es muss stdcall verwendet werden.
Delphi-Quellcode:
function OpenURL(url: PChar) : Integer; stdcall;
Warum hantierst du eigentlich mit dem Win32 Thread API statt TThread zu nutzen?

Nils_13 28. Jan 2007 16:01

Re: Problem mit Threads
 
Der Channel steht aus irgendeinem Grund auf 0, aber ich sehe den Fehler nicht.

Mit oder ohne stdcall; kommt jetzt zusätzlich (kA, warum) das:
---------------------------
Benachrichtigung über Debugger-Problem
---------------------------
In Projekt ... trat ein Problem mit folgender Meldung auf: 'Privilegierte Instruktion bei 0x00af587d'. Prozess angehalten. Mit Einzelne Anweisung oder Start fortsetzen.
---------------------------
OK
---------------------------

Robert Marquardt 28. Jan 2007 16:23

Re: Problem mit Threads
 
Mitdenken. Ich wette mal StatusProc ist auch nicht als stdcall deklariert.

Nils_13 28. Jan 2007 16:46

Re: Problem mit Threads
 
Könnt ihr mir sagen, warum mir Delphi abschmiert, wenn ich stdcall; benutze ? Einmal neugestartet (RESTARTTASTE) und eben gerade noch so, mit dem ausnahmsweise nicht abgestürzten Taskmanager, gerettet.

Robert Marquardt 28. Jan 2007 17:26

Re: Problem mit Threads
 
Es koennte sein das die bass.dll cdecl statt stdcall will. Also StatusProc mal probeweise mit cdecl statt stdcall deklarieren.

Nils_13 28. Jan 2007 17:34

Re: Problem mit Threads
 
Hmm...ich habe gerade herausgefunden, dass OpenURL Delphi aufhängt, wenn dort ein stdcall; steht, bei cdecl; passiert hingegen überhaupt nichts. StatusProc funktioniert mit stdcall.

ste_ett 28. Jan 2007 17:41

Re: Problem mit Threads
 
Hast du Speicher reserviert für den Parameter?
Sonst ist es klar, dass es knallt. :)

Delphi-Quellcode:
procedure TfrmMain.lvDblClick(Sender: TObject);
var
  p: PChar;
begin
  GetMem(p, Length(urls[0]) +1); // Speicher reservieren, da eine lokale Variable nach Durchlauf der Funktion/Prozedur nicht mehr besteht
  StrPCopy(p, urls[0]);
  cthread := StartPlayStream(p);
end;



function OpenURL(url: PChar) : Integer;
var
  icy: PChar;
  Len, Progress: DWORD;
begin
  Result := 0;

// restlicher Code hier...

  FreeMem(url); // Speicher wieder freigeben
end;

Robert Marquardt 28. Jan 2007 17:44

Re: Problem mit Threads
 
Das verwundert mich jetzt aber sehr. Ich habe nochmal bei meinem D6 nachgeschaut und TThreadFunc sollte weder stdcall noch cdecl haben.
Ich habe nicht realisiert das BeginThread ja eine Delphifunktion ist und keine Win32-Funktion.

Robert Marquardt 28. Jan 2007 17:48

Re: Problem mit Threads
 
ste_ett, wenn man den Speicher alloziiert, dann sollte man ihn auch wieder freigeben. p als lokale Variable ist also schlecht.

ste_ett 28. Jan 2007 17:51

Re: Problem mit Threads
 
Zitat:

Zitat von Robert Marquardt
Das verwundert mich jetzt aber sehr. Ich habe nochmal bei meinem D6 nachgeschaut und TThreadFunc sollte weder stdcall noch cdecl haben.
Ich habe nicht realisiert das BeginThread ja eine Delphifunktion ist und keine Win32-Funktion.

BeginThread ruft intern aber auch nur CreateThread auf und der Parameter wird indirekt weitergegeben. :)

Als Parameter wird ThreadProc erwartet oder NULL, wenn keine Parameter übergeben wwerden sollen.

Code:
HANDLE WINAPI CreateThread(
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  SIZE_T dwStackSize,
  LPTHREAD_START_ROUTINE lpStartAddress,
  LPVOID lpParameter,
  DWORD dwCreationFlags,
  LPDWORD lpThreadId
);

DWORD WINAPI ThreadProc(
  LPVOID lpParameter
);
WINAPI ist als __stdcall definiert.

ste_ett 28. Jan 2007 17:55

Re: Problem mit Threads
 
Zitat:

Zitat von Robert Marquardt
ste_ett, wenn man den Speicher alloziiert, dann sollte man ihn auch wieder freigeben. p als lokale Variable ist also schlecht.

s. letzte Zeile in OpenURL(). :)
Die Speicheradresse hat man über den Parameter der Funktion, von da her ist es über eine lokale Variable möglich, da der Ort, auf den der Zeiger zeigt, nicht verloren geht.

Nils_13 28. Jan 2007 17:56

Re: Problem mit Threads
 
Ich habe deinen Code instgesamt 3x angwendet (also ausgeführt):
1: Ungültige Zeigeroperation, wegklickbar, kein Absturz
2: Ungültige Zeigeroperation, wegklickbar, Absturz
3: Ungültige Zeigeroperation, wegklickbar, Absturz

Robert Marquardt 28. Jan 2007 17:59

Re: Problem mit Threads
 
Na dann hat aber Borland Mist gebaut. TThreadProc ist in meinem D6 nicht mit stdcall deklariert.

Gerade geht mir ein Licht auf. StatusProc greift vermutlich auf die VCL zu und die ist natuerlich nicht threadsafe.
Bitte StatusProc posten.

Nils_13 28. Jan 2007 18:02

Re: Problem mit Threads
 
Delphi-Quellcode:
procedure StatusProc(buffer: Pointer; len, user: DWORD); stdcall;
begin
  if (buffer <> nil) and (len = 0) then
    SendMessage(win, WM_INFO_UPDATE, 8, DWORD(PChar(buffer)));
end;

Robert Marquardt 28. Jan 2007 18:38

Re: Problem mit Threads
 
Na das ist gesund. Mist, schon wieder eine Fehlerquelle weniger.

Nils_13 31. Jan 2007 14:43

Re: Problem mit Threads
 
*push*

[ich habe jetzt schon ein paar Tage gewartet]

ste_ett 1. Feb 2007 07:48

Re: Problem mit Threads
 
Lade am Besten mal den Teil per Anhang hoch.
Im Moment muss man sich den code aus verschiedenen Posts zusammensuchen. :)

Nils_13 1. Feb 2007 14:09

Re: Problem mit Threads
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hab was verwechselt... Hier ist das korrekte Projekt. Bitte erst die Komponente des Ornders Komponenten installieren. Wenn nicht, ist der Code dennoch da.

ste_ett 1. Feb 2007 22:03

Re: Problem mit Threads
 
Ich hab mir den Code mal angeguckt.

1)
Du hast kein "stdcall;" als Aufrufkonvention für "OpenURL()". Es funktioniert trotzdem (, da wahrscheinlich stdcall bei dir als Standard eingestellt ist).

2)
Die Exception tritt auf, wenn du auf "urls" zugreifst.
Dyn. Array mit 0 Elementen, du greifst ohne Prüfung auf ein Element zu.

3)
Per Debugger hättest du das alles selbst rausgefunden! :)

Nils_13 2. Feb 2007 10:12

Re: Problem mit Threads
 
Zu
1.: Was genau heißt Standard. Code oder System ?
2.: Ich finde die Stelle wirklich nicht, wo dies der Fall sein könnte. Kannst du es mir sagen ? Bzw.: Ich versteh nicht, wie dies möglich sein kann.
3.: Das habe ich gemacht, bevor dieser Thread eröffnet wurde und während ihr mir weiterhelfen wolltet, habe ich auch debuggt.

Karl-Heinz 15. Feb 2007 16:31

Re: Problem mit Threads
 
Hallo,
habe gestern mit dem gleichen Code herumgespielt (ein Beispielprojekt aus dem Bass-SDK).
Hatte unter D5 die gleichen Probleme.
Die OpenURL()-Procedure muss NICHT mit stdcall oder cdecl deklariert werden; soviel ist klar. Denn die Delphi-Funktion "BeginThread" erwartet einfach nur einen Pointer auf eine Procedure mit einem Pointer-Parameter.

Auch die Lösung, die zu übergebende URL als pchar oder array of char zu übergeben (statt pchar(urlstring) ) brachte keinen Erfolg:
Immer wenn ich in der Procedure OpenUrl (welche von BeginThread aufgerufen wird) nachgesehen habe, was denn als Url-Parameter übergeben wurde, kam - Zufall heraus.

Mein Fazit: Nicht die Funktion BeginThread nutzen, sondern einen eigenen sauberen TThread-Abkömmling schreiben.

Nils_13 22. Feb 2007 17:12

Re: Problem mit Threads
 
Ok. Damit habe ich aber gewisse Startschwierigkeiten. Könnt ihr mir da bitte helfen ?
Delphi-Quellcode:
  type
    TMyThread = class(TThread) // ist aus dem Kopf, kA, ob das so stimmt
      procedure StartThread(?);
      procedure EndThread(?);
    private
   
    public

    end;
 
procedure TMyThread.StartThread(?);
begin
  ??
end;

procedure TMyThread.EndThread(?);
begin
  ??
end;

// Ist jetzt noch die Frage, ob nötige andere Sachen nötig sind
// ?/?? heißt, dass ich nicht weiß, was an diese Stelle muss

oki 22. Feb 2007 17:28

Re: Problem mit Threads
 
Zitat:

Zitat von Nils_13
Hi,
Dieser Code funktioniert nicht:
cthread := BeginThread(nil, 0, @OpenURL, PChar(urls[0]), 0, ThreadId); // urls = TDynStrArray

Dieser Code funkioniert:
cthread := BeginThread(nil, 0, @OpenURL, PChar('http://stream.clubnation.fm'), 0, ThreadId);

In urls[0] steht http://stream.clubnation.fm.

Warum funktioniert der zweite Code, aber der benötigte erste Code nicht ?
In OpenURL werden die korrekten Parameter übergeben (http://stream.clubnation.fm).


Wenn diese Aussage so richtig ist, dann kann es doch nur an PChar(urls[0]) liegen. Der Rest ist doch gleich.

Hänge an deine Einträge in urls doch mal ein #0 ran und teste folgendes:

Delphi-Quellcode:
s := urls[0] + #0;
cthread := BeginThread(nil, 0, @OpenURL, @s[1], 0, ThreadId);
Ist nur so ne Idee.

Gruß oki

Nils_13 22. Feb 2007 19:42

Re: Problem mit Threads
 
So gibt es keine AV. Dafür aber die Meldung, dass er es nicht spielen könnte (Chan=0).

oki 22. Feb 2007 19:51

Re: Problem mit Threads
 
das s als String deklariert sein muss ist klar.

Anders würde soundso der Compiler meckern.

Naja, war nen Versuch wert.

Gruß oki

Nils_13 28. Feb 2007 15:58

Re: Problem mit Threads
 
Kann mir hier wirklich keier mal sagen, wie man einen Threadabkömmling schreiben könnte ? :( :kotz:

Tommy1988 27. Apr 2007 16:19

Re: Problem mit Threads
 
Dazu hätte ich auch noch eine Frage

mit

Delphi-Quellcode:
cthread := BeginThread(nil, 0, @OpenURL, PChar('http://stream.clubnation.fm'), 0, ThreadId);
wird ein RadioStream gestartet und abgespielt, ist es möglich diesen auch wieder zu beenden?

Ich habe eine CheckBox auf meinem Formular, mit der man den Ton abstellen kann, Systemweit das ist das Problem.

Deswegen: ist es möglich, den Ton im Programm abzustellen oder den Thread (Stream) zu beenden?

Nils_13 27. Apr 2007 17:04

Re: Problem mit Threads
 
Oh, ich habe ganz vergessen zu schreiben, dass das Problem schon längst gelöst ist....

Ich habe es so gelöst, dass ich eine 100% falsche Sache an BeginThread übergeben habe und mit einer Variable eine Fehlermeldung, welche dadurch angezeigt werden würde, vermieden. Es geht bestimmt viel besser, aber so funktioniert es.

Tommy1988 27. Apr 2007 17:26

Re: Problem mit Threads
 
kann mir wer vielleicht eine alternative nennen?


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:15 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