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). |
Re: Problem mit Threads
Was funktioniert nicht?
Wird der Thread nict erstellt? Die Prozedur nicht aufgerufen? |
Re: Problem mit Threads
Er meint, er könnte den Stream nicht abspielen, im anderen Fall spielt er ihn ab.
|
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:
Ich habe ein ähnliches Problem mit 'OutputDebugString' gehabt und mir dann so eine (ziemliche dumme) Hilfsroutine geschrieben.
Function StartPlayStream (anURL : String) : THandle;
Begin Result := BeginThread(nil, 0, @OpenURL, PChar(anURL), 0, ThreadId); // urls = TDynStrArray End; |
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:
|
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. :) |
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; |
Re: Problem mit Threads
Bist du mal mit dem Debugger durchgegangen und hast die Variablen und Parameter geprüft?
|
Re: Problem mit Threads
ste_ett hat das Problem sauber diagnostiziert.
Es muss stdcall verwendet werden.
Delphi-Quellcode:
Warum hantierst du eigentlich mit dem Win32 Thread API statt TThread zu nutzen?
function OpenURL(url: PChar) : Integer; stdcall;
|
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 --------------------------- |
Re: Problem mit Threads
Mitdenken. Ich wette mal StatusProc ist auch nicht als stdcall deklariert.
|
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.
|
Re: Problem mit Threads
Es koennte sein das die bass.dll cdecl statt stdcall will. Also StatusProc mal probeweise mit cdecl statt stdcall deklarieren.
|
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.
|
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; |
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. |
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.
|
Re: Problem mit Threads
Zitat:
Als Parameter wird ThreadProc erwartet oder NULL, wenn keine Parameter übergeben wwerden sollen.
Code:
WINAPI ist als __stdcall definiert.
HANDLE WINAPI CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId ); DWORD WINAPI ThreadProc( LPVOID lpParameter ); |
Re: Problem mit Threads
Zitat:
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. |
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 |
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. |
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; |
Re: Problem mit Threads
Na das ist gesund. Mist, schon wieder eine Fehlerquelle weniger.
|
Re: Problem mit Threads
*push*
[ich habe jetzt schon ein paar Tage gewartet] |
Re: Problem mit Threads
Lade am Besten mal den Teil per Anhang hoch.
Im Moment muss man sich den code aus verschiedenen Posts zusammensuchen. :) |
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.
|
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! :) |
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. |
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. |
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 |
Re: Problem mit Threads
Zitat:
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:
Ist nur so ne Idee.
s := urls[0] + #0;
cthread := BeginThread(nil, 0, @OpenURL, @s[1], 0, ThreadId); Gruß oki |
Re: Problem mit Threads
So gibt es keine AV. Dafür aber die Meldung, dass er es nicht spielen könnte (Chan=0).
|
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 |
Re: Problem mit Threads
Kann mir hier wirklich keier mal sagen, wie man einen Threadabkömmling schreiben könnte ? :( :kotz:
|
Re: Problem mit Threads
Dazu hätte ich auch noch eine Frage
mit
Delphi-Quellcode:
wird ein RadioStream gestartet und abgespielt, ist es möglich diesen auch wieder zu beenden?
cthread := BeginThread(nil, 0, @OpenURL, PChar('http://stream.clubnation.fm'), 0, ThreadId);
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? |
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. |
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