AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Bitmap.Canvas -> Form.Canvas ... nix zu sehen
Thema durchsuchen
Ansicht
Themen-Optionen

Bitmap.Canvas -> Form.Canvas ... nix zu sehen

Ein Thema von TERWI · begonnen am 9. Jul 2018 · letzter Beitrag vom 19. Jul 2018
Antwort Antwort
Benutzerbild von TERWI
TERWI

Registriert seit: 29. Mär 2008
Ort: D-49626
381 Beiträge
 
Delphi 11 Alexandria
 
#1

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen

  Alt 17. Jul 2018, 13:19
Das mit den Handles zuweisen hat hier auch nur bedingt geklappt. Der Effekt wie bei meinen weiteren Versuchen:
Die Anzeige kommt, keine Fehler - aber irgendwann friert das OSD ein, obwohl der Datenstrom / Generierung der Quell-BitMap weiter läuft.

Synchronize kann ich hier nicht nutzen, weil ich (im eigentlichen Programm) nicht explizit einen Thread selbst mache, sondern der Thread-Kontext offensichtlich durch den Direct-Show-Filter (Data-Sink Transport-Stream) ensteht - ich habe jedenfalls verschiedene Thread-IDs.

Mittlerweile scheint es dauerhaft (!?) zu funzen. Was hab ich für "Safe" geändert ?
Aufruf des OSD aus dem Parser:
Delphi-Quellcode:
procedure TOSD_data.OnReceiveData(Counter : DWORD);
begin
  if NOT FEnable then exit;
  FormMain.lbl_CountData.Caption := inttostr(FCount); // Visualisierungs-Krücke
  _TextOut(0, 0, inttostr(Counter));
  FOutputCS.Enter;
  try
    FormOSD.OSDUpdate(FBMOSD);
  finally
    FOutputCS.Leave;
  end;
  inc(FCount);
end;
Zuweisung des Image im OSD:
Delphi-Quellcode:
procedure TFormOSD.OSDupdate(BM : TBitMap);
begin
  if NOT Visible then exit;
  FormMain.lbl_CountOSD.Caption := inttostr(FCount); // Visualisierungs-Krücke
  inc(FCount);
  FInputCS.Enter;
  try
    if Assigned(BM) then
      Image.Picture.Bitmap.Assign(BM);
  finally
    FInputCS.Leave;
  end;
end;
Das läuft nun tadellos ohne Exception (auch vorher noch nie) oder Hänger auch über Nacht. Ob ich den Rechner anderweitig stresse, scheint keine Rolle zu spielen.

Ich hab mein komplexes Projekt mal stark vereinfacht und als Anhang mit EXE beigefügt. Das ganze funktioniert wie folgt, besteht aus
- Form Main:
mit 3 Buttons (als Toggle) und 3 Labels zur "Visualisierung".
Dazu hilfsweise ein Thread, der den Datenstrom simuliert. Hier wird einfach nur ein Counter hochgezählt. Die Wiederholrate ist hier mit Sleep(Randomzahl) zwischen 50 und 250 ms angelegt, damit das "wie in echt" zufällig ist.

- Unit OSD_Data:
Entspricht meinem Daten-Parser. Wird getriggert durch den Thread und bekommt die forlaufende Zahl, welche einfach nur ein eine (formatierte) BitMap geschrieben wird.
Ein weiterer interner Zähler (<= Thread-Counter) zählt die Aufrufe mit, wenn solange der Parser aktiv (mitlesen) ist.
"Enable" und "ShowData" wird von der Main-Form gesteuert.

- Form OSD:
Ist einfach nur eine Anzeige der fortlaufend generierten Parser-Bitmap und wird indirekt von der Main-Form über den Parser/OSD-Data gesteuert. D. h., ausschliesslich der Parser greift (direkt) auf diese Form zu.
Aufruf von OSD_Show zeigt die Form an oder schliesst diese, OSD_Update "assigned" die Parser-Bitmap auf das interne Image.

Funktion der Buttons:
Sind als Toggle ausgelegt, d.h. Klick -> aus, Klick -> an usw.

- Start/Stop Source
Startet/pausiert den Thread. Das Label neben dem Button zeigt die generierte, fortlaufende Zahl an.
Hat der Thread (Daten-Strom) Pause, passiert logo nix im Parser und OSD.

- Start/Stop Parser:
Wie Button "Start/Stop Source". Im eigentlichen Programm dient das zum Ein-/Ausschalten des Hintergrund-Monitoring/Datemsammeln (auch ohne OSD).
Das Label zum Button zeigt die tatsächlich gelesenen "Datenpakete" an.

- Start/Stop OSD:
Wie Button "Start/Stop Source". OSD_Show intialisiert jedes mal das Image in grün mit "Hello World !".
Solange Source und Parser auf STOP sind, passiert nix. Bei OSD_update wird das Image rot mit der aktuellen Zahl der Source-Threads.

Erstellt mit Delphi 2009 auf Win 8.1.
Angehängte Dateien
Dateityp: zip OSD_Test.zip (275,1 KB, 6x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.378 Beiträge
 
Delphi 12 Athens
 
#2

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen

  Alt 17. Jul 2018, 13:22
Synchronize kann ich hier nicht nutzen, weil ich (im eigentlichen Programm) nicht explizit einen Thread selbst mache, sondern der Thread-Kontext offensichtlich durch den Direct-Show-Filter (Data-Sink Transport-Stream) ensteht - ich habe jedenfalls verschiedene Thread-IDs.
TThread.Synchronize(nil, deineProzedur);


Oder einen ExternalThread erstellen.
TThread.Current gibt dir eine TThread-Instanz für einen fremden/unbekannten Thread. (ich weiß aber nicht seit wann es das in der RTL schon gibt)
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (17. Jul 2018 um 13:25 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von TERWI
TERWI

Registriert seit: 29. Mär 2008
Ort: D-49626
381 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen

  Alt 18. Jul 2018, 15:06
Neues ...

@jaenicke
System.TMonitor.Enter/Exit auf irgendeine andere Bitmap als innerhalb der aufrufenden Klasse anzuwenden, geht hier völlig in die Hose. Programmabsturz.
Da ich keine Ahnung von der Anwendung dieser Methoden habe und auch nix wirklich gescheites dazu finde, hab ich das erst mal verworfen.
Und Zuweisen von Handles von Quell- zu Ziel-Bitmap scheint ohne Release (BM ungültig ?!) auch irgendwie nicht zu funzen. Für jedes Update eine neue BM zu erzeugen ist hier nicht unbedingt erstrebenswert.

Betreff Synchronize:
Remi Lebeau schrieb im SOF, das NIL als Param das gleiche wäre wie TThread.CurrentThread. Er sollte es wissen.
Desweiteren las ich irgendwo, das es angeblich nix anderes (?!) machen soll wie CSLock.Enter/Leave. Hhhmmm.
Allerdings:
Mit Synchronize(NIL, ...) gibt es hier (sowohl in der o.g. Demo und meinem eigentlichen Proggy) keinen Absturz oder AV's - aber wieder mal bleibt schlicht und ergreifend die Anzeige "irgend wann mal hängen".
Der gleiche Effekt, als wenn ich meine Quell-BitMap NICHT mit Assign zuweise, sondern stattdessen Canvas.CpoyRect oder Canvas.Draw probiere.

Auf was wird da eigentlich "gesynchronized" ? Auf den Main-Thread/-Form der App ? Falls ja, da will ich doch gar nicht hin ....
Ist denn eine extra OSD-Form nicht auch ein weiterer Thread ? Auf die/den will ich aber (aus einem wiederum weiteren Fred / DirectSHow) schreiben ....
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.074 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen

  Alt 18. Jul 2018, 15:29
Ist denn eine extra OSD-Form nicht auch ein weiterer Thread ? Auf die/den will ich aber (aus einem wiederum weiteren Fred / DirectSHow) schreiben ....
Nein!
Erzeuge dir doch dazu mal in der OSD-Form ein FormCreate-Eventhandler und schreibe da wie folgt:

Delphi-Quellcode:
if MainThreadID = TThread.Current.ThreadId then
  ShowMessage('Ich bin im Hauptthread'!)
else
  ShowMessage('Ich bin in einen anderen Thread Context:' + UIntToStr(TThread.Current.ThreadId));
PS: Bitte nicht mehr "Fred" für Thread schreiben. Das ist genauso schlimm wie "Schlepptop und Teflon zum Bleistift".
  Mit Zitat antworten Zitat
Benutzerbild von TERWI
TERWI

Registriert seit: 29. Mär 2008
Ort: D-49626
381 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen

  Alt 18. Jul 2018, 16:47
TThread.Current.ThreadId kennt D2009 nicht, aber TThread.CurrentThread.ThreadId. Schreibfehler oder Tokyo ?

Die aufrufende Methode:
Delphi-Quellcode:
procedure TTeletext.ShowTTxt(Mode : boolean; Page : integer);
var
  ID1, ID2 : cardinal;
begin
  ID1 := MainThreadID;
  ID2 := GetCurrentThreadId; // TThread.CurrentThread.ThreadId;
  if ID1 = ID2 then
    LOG('ShowTTxt', 'Ich bin im Hauptthread')
  else
    LOG('ShowTTxt', 'Ich bin in einen anderen Thread Context:' + IntToStr(ID2));

  if not Assigned(FOSD) then
  begin
    FOSD := TFormOSD.Create(nil);
  end;

  FOSD.OSDshow(Mode, FBMOSD);

  SetPageNumber(Page);
  FShowTTxt := Mode;
end;
Die empfangende Methode:
Delphi-Quellcode:
procedure TFormOSD.FormCreate(Sender: TObject);
var
  ID1, ID2 : cardinal;
begin
  ID1 := MainThreadID;
  ID2 := GetCurrentThreadId; //TThread.CurrentThread.ThreadId;
  if ID1 = ID2 then
    LOG('FormCreate', 'Ich bin im Hauptthread')
  else
    LOG('FormCreate', 'Ich bin in einen anderen Thread Context:' + IntToStr(ID2));
  ...
end;
Mein LOGGER sagt:
Code:
[17:35:53:113] [TTXT - ShowTTxt]: Ich bin im Hauptthread
[17:35:53:116] [OSD - FormCreate]: Ich bin im Hauptthread
Letzteres ist mir völlig unbegreiflich, weil ich das vor ein paar Tagen explizit & ausführlich getest habe und da waren ID1 und ID2 noch unterschiedlich ! ... sonst hätte ich das in den Postings vorher nicht so besimmt geschrieben.

Desweiteren:
ID2 := GetCurrentThreadId; funktioniert - hatte ich dieser Tage auch so.
ID2 := TThread.CurrentThread.ThreadId; führt beim Beenden des Progs zu einer AV - siehe angehängtes Bild.

.... ich versteh die Welt nicht mehr.
Angehängte Grafiken
Dateityp: jpg Thread_Err.jpg (13,0 KB, 4x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von TERWI
TERWI

Registriert seit: 29. Mär 2008
Ort: D-49626
381 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen

  Alt 18. Jul 2018, 16:56
Nachtrag: .... die Welt ist doch noch nicht untergegangen.
Das o.g. noch mal in meine Update-Methode eingebaut:
Delphi-Quellcode:
procedure TTeletext.UpdateOSD();
var
  ID1, ID2 : cardinal;
begin
  ID1 := MainThreadID;
  ID2 := GetCurrentThreadId; // TThread.CurrentThread.ThreadId;
  if ID1 = ID2 then
    LOG('UpdateOSD', 'Ich bin im Hauptthread')
  else
    LOG('UpdateOSD', 'Ich bin in einen anderen Thread Context:' + IntToStr(ID2));
  if NOT FShowTTxt then exit;
  if NOT Assigned(FOSD) then exit;
  FOutputCS.Enter;
  try
    FOSD.OSDupdate(FBMOSD);
  finally
    FOutputCS.Leave;
  end;
end;
Dazu sagt der LOGGER (bei jedem Aufruf):
Code:
[17:49:36:178] [TTXT - UpdateOSD]: Ich bin in einen anderen Thread Context: 1572
Aha ! Bin ich also doch nicht völlig verkalkt.

Geändert von TERWI (18. Jul 2018 um 16:59 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.074 Beiträge
 
Delphi 10.4 Sydney
 
#7

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen

  Alt 18. Jul 2018, 19:59
Nichtsdestotrotz greifst du auf Ressourcen innerhalb des Kontextes deines Update-Threads zu, die ganz eindeutig zum Mainthread gehören.
Dazu wurde dir auf den vorigen Seiten genügend oft gesagt, dass man das nicht macht.
Das ist kein kurzes Anhalten in der Parkverbotszone, das ist ein Wenden auf der Autobahn.
Du musst zwingend mit TThread.Syncronize(nil,...) arbeiten.
  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 02:30 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz