Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Bitmap.Canvas -> Form.Canvas ... nix zu sehen (https://www.delphipraxis.net/197007-bitmap-canvas-form-canvas-nix-zu-sehen.html)

TERWI 9. Jul 2018 14:44

Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Das Ziel:
Ich erzeuge in einer Unit meines Proggis eine BitMap (ca. 600 X 600) und fülle diese kontinuierlich mittels FillRect und Textout mit irgendwelchen 'bunten' Sachen. Das klappt auch so weit ....
Neben dem speichern 'on demand' soll diese Bitmap als Kontrolle auch jederzeit zu sehen sein - d.h. ich möchte gerne diese (permanent geänderte) BM auf einer separatem Form (bei Bedarf) sehen.

Mein Prob:
1. Versuch: Form.Canvas auf BitMap.Canvas setzen ... nogo
2. Versuch: In Form.OnRepaint mit Canvas.Draw die BitMap ... nogo
3. Versuch: Direkt auf Form.Canvas pinseln - mit oder ohne repaint ... nogo
Ich hab immer nur das default graue Canvas der Form, obwohl sich da definitiv was zeigen sollte.

Das eruegute/geänderte BitMap ist jeweils so weit OK - aber ich sehe nix in der Form, flackert nicht mal ...

Ich bin da nicht so der Held in Sachen Graphics und mir gehen die Ideen aus.
Wie macht man das richtig ?

TiGü 9. Jul 2018 15:06

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Zu 2.:
Machst du denn auch ein Form.Repaint, sobald du das Bitmap auf den Form.Canvas gezeichnet hast? (Form.Canvas.Draw oder Form.Canvas.StretchDraw)

TERWI 9. Jul 2018 15:25

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Delphi-Quellcode:
// OSD-Form
type
...
  public
    FBitmap : TBitMap;
  end;

...

procedure TFormOSD.FormPaint(Sender: TObject);
begin
  if Assigned(FBitmap) then
    Canvas.Draw(0, 0, FBitmap);
end;
...

// Calling Unit:
type
  FBMOSD : TBitmap; // die zu bearbeitende BM

  ...

  // ... wenn was geändert wurde:
  if Assigned(FormOSD) then
  begin
    ... BitMap Inhalt ändern ...
    FormOSD.FBitmap := FBMOSD; // zur Sicherheit noch mal zuweisen
    FormOSD.Repaint;
  end;

Uwe Raabe 9. Jul 2018 15:26

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Du kannst einfach ein TImage auf das Form platzieren und bei Bedarf dem Image.Picture.Bitmap deine Bitmap zuweisen.

TERWI 9. Jul 2018 15:45

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
... das gibt eine nette Zugriffsverletzung.

Neuer Versuch:
Ich schreibe direkt aus dem Programm auf's Canvas der OSD-Form.
Z.B.
Delphi-Quellcode:
FormOSD.Canvas.TextOut(X, Y, ansistring(Text));
ohne Repaint u. a. --- das geht !
... ist aber nicht Sinn der Sache.

TERWI 9. Jul 2018 16:02

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Kleine Korrektur:
Ich hab in der Eile 'Image.Create/Free' vergessen.
Das ändert aber nichts an der mangelhaften / keine Ausgabe.

TiGü 9. Jul 2018 16:24

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Beispielprojekt als ZIP hier hochladen?

TERWI 9. Jul 2018 16:36

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Wäre theoretisch moglich - aber in der Komplexität steigt da mit Sicherheit niemand auch nach längerem nicht durch ... (hab ich schon nach 1 Woche Pause meine Sorgen)
Nächstes Prob wäre: Die Daten kommen aus einem DVB-Transport-Strom und es müsste der Tester schon ein DVB-Gerät oder adäquate TS-Files haben.

Wer da ernsthaft (!) interesse dran hat ... melden.

Hier ist einfach nur das Prob: Permanent generierte/geänderte Bitmap im Proggie in externer Form ebenso permanent anzeigen.
Mit Direktzugriff auf die OSD-Form geht das ja ... aber ich will (!) das mit Übergabe aus einer (zuvor generierten) Bitmap machen, die ich auch noch für anderes brauche.

Uwe Raabe 9. Jul 2018 16:47

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

Zitat von TERWI (Beitrag 1406799)
Kleine Korrektur:
Ich hab in der Eile 'Image.Create/Free' vergessen.
Das ändert aber nichts an der mangelhaften / keine Ausgabe.

Mit "Du kannst einfach ein TImage auf das Form platzieren" meine ich natürlich "im Form-Designer" und nicht zur Laufzeit.

Wenn deine Änderungen in dem Image nicht angezeigt werden, dann solltest du allerdings schon ein Beispielprojekt (ändere Bitmap, Anzeige auf dem Form) hier hochladen, damit wir sehen können, was da passiert. Ich habe so den Verdacht, daß uns da eine wesentliche Information noch fehlt.

himitsu 9. Jul 2018 17:36

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Ist dein Bitmap Vollbild auf der Form? Wenn nicht, dann eine TPaintBox drumrum.

* auf Bitmap zeichnen
* und in Form.Repaint, bzw. PaintBox.Repaint oder .Refresh auslösen, damit im OnPaint (wo dein Draw drin ist) das Aktuelle angezeigt wird.
** wobei Repaint/Refresh sofort zeichnet, also wäre .Invalidate vielleicht besser, falls du schneller/öfters was am Bitmap änderst, damit nicht "sofort" sondern erst "gleich" gezeichnet wird, sobald die GUI später die Kontrolle zurückbekommen hat



TImage und da ins Bitmap zeichnen, bzw. umständlich das externe Bitmap zuweisen (ins Interne kopieren), da wird über Bitmap.OnChanged ein Repaint des TImage ausgelöst.

TERWI 9. Jul 2018 17:40

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
"FormOSD" ist eine eigenständige Form und wird in meine Unit eigebunden.
Das Image wird dort korrekt de-/initialisiert, Alignment ist alClient.
Die Form wird zur Laufzeit (vor Zugriff) mittels CLientWidth/Height auf die gleiche Größe meiner BitMap gesetzt. Sollte also eigentlich alles passen.

Tut es aber nicht "tuten" - alles grau. Direktes schreiben auf FormOSD funktioniert so weit (auch ohne geflacker bei schnellem wiederholtem Update, wa ich eigentlich erwartet hatte).
Dein Verdacht, daß da die eine oder andere wesentliche Information noch fehlt ist sicherlich begründet - aber wie schon gesagt ist das ganze Projekt nicht wirklich in Einzelteilen zu zerlegen, hier gejt's um eben dieses spezielle Problem:

Bitmap to Form.

Redeemer 9. Jul 2018 17:54

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Du schreibst wohl zu früh.
TImage.Canvas kann seine Größe nicht zur Laufzeit anpassen. Sie wird beim ersten Schreiben eingefroren. Möglicherweise ist die Größe zum Zeitpunkt des ersten Schreibens nicht richtig.

Ohne Quellcode kann dir aber wohl keiner helfen.

TERWI 9. Jul 2018 18:47

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
ach Leute, ihr immer mit Quellcode ... verstehe ich ja zum verstehen - aber was ist an meinen Fragen so unverständlich, das man's auch nicht auch ohne verseht ? ... sorry.

Ist im Prinzip das gleich wie in #3.
Bitmap an OSD.Canvas: ... da tut sich nix !
Direkt schreiben an OSD.Canvas: ... ist OK !!!

Ich verstehe eben genau dieses "Feature" nicht.

@Redeemer
Ob mit oder ohne TImage - geht nur direkt an Canvas.

TiGü 9. Jul 2018 20:00

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Wir fragen ja nicht aus Spaß an der Freude nach Quelltext.
In 99 % der Fälle ist es nämlich so, dass der Ersteller der Ursprungsfrage Informationen vorenthält, die er als unwichtig erachtet, die aber entscheidende Details sind.

Oft ist es auch so, dass beim Erstellen eines abgespeckten Beispielprojektes das Problem wundersamerweise verschwindet und man drauf kommt, warum etwas nicht funktioniert.

Die Zahl der Threads, die ich zu schreiben begonnen hatte (wohlbemerkt mit Beispielprojektes) ist doppelt bis dreimal so hoch wie meine tatsächlich gestellten Fragen, weil ich dann plötzlich meinen Fehler gesehen habe.

Ich verstehe auch nicht, warum das so ein Problem für dich ist?
Mach doch zwei Formulare und einen Timer.
Im OnTimer zeichnest du dann aufs zweite Formular einmal so, wie es jetzt funktioniert und dann nochmal so, wie du es gerne hättest.
Irgendwelche zufälligen Linien und bisschen Text.

Ich möchte einen symbolischen Euro wetten, dass du eigentlich ein Threading-Problem hast.
Der DVB-Stream wird ja wahrscheinlich nicht im VCL-Mainthread empfangen, dekomprimiert und das OSD-Menü gezeichnet...nicht wahr?

jaenicke 9. Jul 2018 20:13

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von TERWI (Beitrag 1406813)
ach Leute, ihr immer mit Quellcode ... verstehe ich ja zum verstehen - aber was ist an meinen Fragen so unverständlich, das man's auch nicht auch ohne verseht ? ... sorry.

Daran ist nichts unverständlich, aber das Problem ist, dass alles was du von dem Quelltext zeigst auch funktioniert. Da muss schon noch etwas anderes sein. Und das sehen wir nicht.

Damit du das auch glaubst... im Anhang liegt ein Beispiel mit exakt deinem Quelltext. Aber das Entscheidende dürfte der Quelltext sein, den ich hinzufügen musste, damit es klappt, nämlich den zum Erzeugen, Setzen der Größe und Füllen des Bitmaps usw.
Wie gesagt, alles was du oben an Quelltext gezeigt hast, ist da exakt so drin. Abgesehen davon, dass du da ein type statt eines var drin hast (type FBMOSD : TBitmap; ).

Die einzigen direkten Abbruchbedingungen in Draw sind übrigens, dass die Grafik nil oder Empty ist. Was passiert eigentlich, wenn du einen Haltepunkt auf das OnPaint-Ereignis setzt. Kommst du da an? Wird das Draw ausgeführt?

TERWI 11. Jul 2018 13:17

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Es klappt immer noch nicht - ABER:
Das scheint ganz offensichtlich nicht daran zu liegen, ob ich meine erstellte BitMap direkt in das Canvas der OSD-Form schreibe oder ggf. extra noch ein Image in die Form packe und da rein schreibe.

Anscheinend wir hier zur Laufzeit meine FBMOSD-Bitmap irgendwie "zerballert", so dass kein Inhalt mehr erscheint und das Canvas dort nach RePaint wieder "grau" wird.

Ich nutze lediglich FillRect und TextOut af dem Canvas - mittlerweile habe ich alles ausmarkiert, so das eigentlich das BM nur noch einmal zum Start schwarz initialisiert wird und dann betreff Anzeige gar nichts mehr passiert.

Das Eigenartige:
Das passierte vorgestern "sofort" - OSD immer grau (Deshalb meine Anfrage).
Nun kann es auch mal 1-10 Sek. oder länger dauern, bis es "knallt".
Der Daten-Parser und Rest des Programms läuft aber ungehindert problemlos weiter.
... ich finde da einfach keinen Fehler.

OK - ich weiß: Ohne Einblick in den Source ist da schwer zu helfen ... aber was gibt es da für Möglichkeiten, eine BitMap zu zerstören, wenn man eigentlich gar nichts damit anstellt ???

himitsu 11. Jul 2018 13:21

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

Zitat von Redeemer (Beitrag 1406812)
TImage.Canvas kann seine Größe nicht zur Laufzeit anpassen. Sie wird beim ersten Schreiben eingefroren.

Nein, das TImage.Canvas ist immer so groß, wie die TImage-Komponente,
aber die Grafik im TImage/TPicture ändert natürlich nicht seine Größe. (beim ersten Zugriff wird es so groß erstellt, wie TImage zu diesem Zeitpunkt ist)

Auf TImage.Canvas zeichnet man auch nicht drauf!
TImage.Picture.Graphic.Canvas
TImage.Picture.Bitmap.Canvas (beim Zugriff auf TImage.Picture.Bitmap wird in TImage.Picture.Graphic ein neues Bitmap erstellt, wenn dort kein TBitmap drin ist)
...
halt was in dem Picture.Graphic für ein Typ drin steckt

TiGü 11. Jul 2018 13:25

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

Zitat von TiGü (Beitrag 1406815)
Ich möchte einen symbolischen Euro wetten, dass du eigentlich ein Threading-Problem hast.
Der DVB-Stream wird ja wahrscheinlich nicht im VCL-Mainthread empfangen, dekomprimiert und das OSD-Menü gezeichnet...nicht wahr?

kwT

TERWI 11. Jul 2018 13:57

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
... es formt sich was 8-) - kleinen Moment, muss noch was testen ...

TERWI 11. Jul 2018 14:28

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Hölle - es funzt !
Delphi-Quellcode:
procedure TForm_OSD.Update(BitMap : TBitMap);
begin
  if Assigned(Bitmap) then
  begin
    Image.Picture.Bitmap.Assign(BitMap);
//    Image.Repaint;
  end;
end;
Allerdings: Es flackert deutlich sichtbar (nervig) in diesen o.g. unrythmischen ABständen, zu denen die Anzeige vorher völlig verschwand.
Spielt dabei anscheinend keine Rolle, ob Image.Repaint ausmarkiert ist oder nicht.
... wenn das flaclern nun noch zu beseitigen wäre ... Hauptgewinn !

@ TiGü:
Logo spielt da ein Thread mit, sonst wäre das alles ein Glücksspiel, bzw. Bild/Ton würden je nach "Abfrage-Umfang" ewig stottern...
Mache ich etwa wie folgt:
- Mein DS-Sink-Filter schickt TS-Datenblöcke (i.d.r. hier 512KB je ca. 0.5s) an alle "zuhörenden OnTsReceive" Methoden.
- Jeder TS-Block wird in eigene Puffer kopiert und dann je ein Thread gestartet, der die Daten auswertet und ggf. anzeigt (Ziel: Anzeige auch eigener Fred).

TERWI 11. Jul 2018 15:56

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Hab numehr diverses zum Thema "Flackern" nachgesucht, bin aber nicht wirklich fündig geworden.
"DoubleBuffered" an/aus in der OSD-Form bringt nichts.
Beim TImage scheint es so was nicht zu geben ?

Folgendes probiert:
Delphi-Quellcode:
procedure TForm_OSD.Init(BitMap : TBitMap);
begin
  if Assigned(Bitmap) then
  begin
    Image1.Picture.Bitmap.Assign(BitMap);
  end;
end;

procedure TForm_OSD.Update(BitMap : TBitMap);
begin
  if Assigned(Bitmap) then
  begin
    Image.Picture.Bitmap.Canvas.Draw(0, 0, Bitmap);
  end;
end;
Ich rufe einmal INIT auf und danach nur UPDATE.
Das funktioniert zwar (auch) und flackert nicht - ABER:
... zeigt eine Weile meine Änderungen des FBMOSD an, bleibt dann aber einfach "stehen" (Bildinhalt bleibt da).
D.h., das wo zuvor immer blankes Panel oder flackerndes Image zu erwarten war.

Mir gehen die Ideen aus ... was ist das ?

Nachtrag:
BitMap FBMOSD hat immer den gleichen Zeiger und die gleichen Abmessungen - ist da der interne Speicher weg/woanders ???

Rollo62 11. Jul 2018 15:59

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Delphi-Quellcode:
  if Assigned(Bitmap) then
  begin
    if Image.Picture.Bitmap.Canvas.BeginScene then
    begin
       Image.Picture.Bitmap.Canvas.Draw(0, 0, Bitmap);
       Image.Picture.Bitmap.Canvas.EndScene;
    end;
,,,
Hilft das ?

Aber ich glabe eher da ist irgendwas anders mit Threads im Gange bei dir.

Rollo

Uwe Raabe 11. Jul 2018 16:00

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

Zitat von TERWI (Beitrag 1406934)
- Jeder TS-Block wird in eigene Puffer kopiert und dann je ein Thread gestartet, der die Daten auswertet und ggf. anzeigt (Ziel: Anzeige auch eigener Fred).

Wie genau wird denn die Bitmap aus dem Thread angezeigt? Du weißt schon, daß du keine VCL-Controls (z.B. TImage) aus einem Thread heraus verwenden kannst?

TERWI 11. Jul 2018 16:08

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

Wie genau wird denn die Bitmap aus dem Thread angezeigt? Du weißt schon, daß du keine VCL-Controls (z.B. TImage) aus einem Thread heraus verwenden kannst?
Der Thread arbeit nur in einer Schleife den TS-DatenBlock ab.
Es greift auch niemand anderes auf den Thread zu.
Der DatenBlock selbst wird wieder in Teile gesplittet und evaluiert - das Ergebnis daraus wird angezeigt.
Soweit ich das bisher feststellen konnte, ist das alles (noch) schnell genug, bevor ein neuer DatenBlock einrifft (ca. alle o,5 Sek.)
Zur Sicherheit habe ich noch ein Blocking eingebaut, das kein neuer Block akzeptiert wird, so lange der aktuelle noch nicht fertig ist.

Warum kann ich kein TImage aus einem Thread aufrufen ?
Scheint doch so weit nach Hindernissen zu funzen - aber es flackert halt ...

Ich versuche mal einen Auszug meines Threads zu posten, ohne das es den Server sprengt :)

Uwe Raabe 11. Jul 2018 16:24

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

Zitat von TERWI (Beitrag 1406940)
Warum kann ich kein TImage aus einem Thread aufrufen ?
Scheint doch so weit nach Hindernissen zu funzen

Zitat:

Zitat von TERWI (Beitrag 1406937)
Das funktioniert zwar (auch) und flackert nicht - ABER:
... zeigt eine Weile meine Änderungen des FBMOSD an, bleibt dann aber einfach "stehen" (Bildinhalt bleibt da).

Delphi: Why VCL is not thread-safe? How can be?

TERWI 11. Jul 2018 16:41

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Hmmm ... hier arbeiten aber doch eigentlich keine 2 (oder mehr) Fredl's gegeneinander.

Diese Unit wird in einem CallBack getriggert, eingehende Daten in einen eigenen Puffer kopiert.
Danach gehts gleich zurück zum Caller - zuvor wird noch der Auswerte-Thread gestartet, der die Daten zwecks Inkonsistenz aus dem internen Puffer liest.
Und wie gesagt: So lange der Thread arbeitet (interne Kontrollvariable) werden keine neuen Daten in der CallBack-Methode akzeptiert.
Kann zu minimalem Datenverlust, bzw. erneutem warten darauf resultieren, ist aber noch nicht vorgekommen - also nicht das (Zeit-) Problem.

D.h., der Thread arbeitet stur seine Daten ab und zeigt die (normalerweise) auch nach Auswertung korrekt an.
Auch die OSD-Form (hier hilfweise als extra Form) wird von nichts & niemand anderem als genau diesem Thread aufgerufen. M.E.n kann also auch da kein Konflikt auftreten.

"ThreadSafe" muss die OSD-Form doch gar nicht, sein weil keine weiteren Fredi'S (gleichzeitig) zugreifen.
Der Thread ist ledigliglich dazu gedacht, nicht ggf. den aufruferenden Dispatcher des DS-Filters zu blockieren um nicht den Daten-Strom des restlichen Direkt-Show-Systems zu blockieren.

Diese Funktionsweise ist schon seit Jahren hier getestet und läuft ansonsten tadellos.

Hab ich da einen eklatanten Denkfehler ?

Absolut unverständlich ist mir, warum es mit einem TImage mehr oder weniger gut funzt, mit direktem Schreiben auf's Canvas der Form oder dem TImage nicht.

jaenicke 11. Jul 2018 16:41

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

Zitat von TERWI (Beitrag 1406940)
Warum kann ich kein TImage aus einem Thread aufrufen ?

Weil die entsprechenden Klassen nicht threadsicher sind. Es ist also ein Glücksspiel. Es kann durchaus mal funktionieren, aber es gibt auch oft unerklärliche Probleme.

Im übrigen gilt das auch für TBitmap. Auch das ist nicht threadsicher. Du kannst also nicht in deinem Verarbeitungsthread eine TBitmap erzeugen und diese dann an den Hauptthread zur Anzeige weiterreichen.

Damit bin ich vor einigen Jahren einmal selbst auf die Nase gefallen.

TiGü 11. Jul 2018 16:51

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
quod erat demonstrandum! :roll:

9. Jul 2018, 21:00 Uhr - Beitrag #14

Sagt dir der Begriff "VCL-Mainthread" bzw. "Main VCL Thread" etwas?
Da haste deinen weiteren Thread.

TERWI 11. Jul 2018 16:58

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Die DVB-PSI-Abteilung meines (Langzeit-)Projekts arbeitet mit exakt den gleichen Funktionen betreff Callback und Thread samt Puffer und anderen Hilfsfunktionen. Quasi eine 1:1-Kopie.
Auch da werden Daten daraus angezeigt, gelesen, verwendet. Dort läuft alles wie "geschmiert".
Der einzige Unterschied: Ich gebrauche dort kein BitMap.

Da stört es den "VCL-(Main)thread" auch nicht die Wurst oder so ...

Uwe Raabe 11. Jul 2018 17:03

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

Zitat von TERWI (Beitrag 1406949)
Der einzige Unterschied: Ich gebrauche dort kein BitMap.

Zitat:

Zitat von jaenicke (Beitrag 1406947)
Im übrigen gilt das auch für TBitmap. Auch das ist nicht threadsicher.

Na sowas...

TERWI 11. Jul 2018 17:17

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Sorry, wenn es so erscheint, als wenn ich mich (bewusst oder absolut) dumm stelle ...

Wie ist den bitte "threadsicher" (genau !) definiert ?
Meiner Erkenntnis nach gilt das für den Fall, wenn (in einer Form, Unit, Methode, ...) der zeitgleiche oder auch zeit-überschreibende Zugriff auf "den selben" Datenbereich (oder Methode ?!) verhindert wird.
Gilt für lesen wie scheiben !?

Meine Form-OSD bekommt hier aber immer nur einen "Ping" von immer dem gleichen Aufrufer immer der Reihe nach. Da überschneidet sich nix. Keine weiteren Anfragen/Aufgaben anderen Threads.
Wo ist da ein Thread-Problem betreff Sicherheit ???

Bitte erkärt's mir.

himitsu 11. Jul 2018 17:21

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

Zitat von TERWI (Beitrag 1406951)
Wie ist den bitte "threadsicher" (genau !) definiert ?

thread safety
Per se so, dass nur ein Thread gleichzeitig damit etwas machen darf.
Viele Komponenten verwenden aber auch globale Dinge (z.B. Default-Instanzen für Brush, Pen, Font usw.), welche auch von der Form und anderen Komponenten immer wieder zum Malen genutzzt werden ... aus dem Hauptthread heraus.

thread affinity
Bezüglich GDI+ und Dergleichen, auf welchem die VCL basiert, da dürfen/können viele Dinge nur in dem Thread verwendet werden, in welchem sie erstellt wurden.
https://blogs.msdn.microsoft.com/old...13-11/?p=33783

jaenicke 11. Jul 2018 17:22

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Eine mögliche Lösung ist ein HBitmap zu verwenden und das nur in die eine oder andere TBitmap Instanz einzukoppeln. Sprich HBitmap im Thread erzeugen, an Handle einer TBitmap Instanz zuweisen, darauf zeichnen und dann nur das Handle weitergeben. Dieses Handle kann man dann im Hauptthread wieder in ein TBitmap werfen um damit zu arbeiten.

Soweit ich weiß ist das vollkommen in Ordnung dieses HBitmap in mehreren Threads weiterzureichen solange nur ein DC darauf aktiv ist. Solange keine parallelen Zugriffe erfolgen, das also ggf. gesichert wird, soweit ich weiß auch mehrere DC.

Alternativ kann man natürlich auch nur mit der API, HBitmap und DCs arbeiten, das sollte meines Wissens immer in Threads gehen solange keine parallelen Zeichenzugriffe erfolgen.

Aber das alles ist schon eine Weile her, ich würde das zur Sicherheit noch einmal nachlesen... :wink:

TERWI 11. Jul 2018 17:40

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Jetzt bin ich etwas verwirrt (überfordert...)
Hier mal auszugsweise die CREATE der besagten Unit:
Delphi-Quellcode:
constructor TDATA2.Create();
begin
  inherited Create;
  ...
  FParserThread := TParserThread.Create(Self);
  FParserThread.SuspendWork;
  FParserThread.Resume;
  ...
  FFont           := TFont.Create;
  FFont.Name      := 'Lucida Console';
  FFont.Size      := 16;
  FFont.Style     := [fsBold];
  FFont.Color     := clWhite;
  ...
  FBMOSD                   := TBitMap.Create;
  FBMOSD.PixelFormat       := pf32bit;
  FBMOSD.Canvas.Brush.Color := clBlack;
  FBMOSD.Canvas.Font.Assign(FFont);
  FTextHeight              := FBMOSD.Canvas.TextHeight('X');
  FTextWidth               := FBMOSD.Canvas.TextWidth('X');
  FBitmapWidth             := FTextWidth * 40;
  FBitmapHeight            := FTextHeight * 25;
  FBMOSD.Width             := FBitmapWidth;
  FBMOSD.Height            := FBitmapHeight;
  _FillRect(0, 0, FBitmapWidth, FBitmapHeight, clBlack);
  ...
end;
Zur Erinnerung:
FBMOSD wird NICHT im HauptThread oder von sonstigen Threads verwurstet, sondern lediglich in einer (zuvor jedoch IM Hauptthread erzeugten) separaten OSD-Form - extra nur (hilsfsweise) für diese Unit.
Hilft das weiter ?

jaenicke 11. Jul 2018 19:00

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
In welchem Threadkontext wird denn auf die Bitmap gezeichnet? Das ist im Grunde die einzige Stelle, die wir noch nicht konkret gesehen haben. Aber das ist genau entscheidend.

Im Zweifelsfall genügt ein Stacktrace, wenn du an der Stelle einen Haltepunkt setzt und anhältst.

TData2.Create wird ja noch deinen Ausführungen im Hauptthread aufgerufen, oder?

TERWI 11. Jul 2018 19:03

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Siehe #26.

KodeZwerg 11. Jul 2018 19:48

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Hab mich vertan, tut mir leid für msg.

jaenicke 11. Jul 2018 21:13

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

Zitat von TERWI (Beitrag 1406960)
Siehe #26.

Dort verstehe ich es so als ob der Thread durchaus mit der Ausgabe und sogar einem VCL-Formular zu tun hat:
Zitat:

Zitat von TERWI (Beitrag 1406946)
Auch die OSD-Form (hier hilfweise als extra Form) wird von nichts & niemand anderem als genau diesem Thread aufgerufen. M.E.n kann also auch da kein Konflikt auftreten.

Beides ist aber aus einem Thread heraus verboten.

Ich habe nicht umsonst (mit wenig Resonanz leider) den Beginn einer Multithread-Komponentenbibliothek veröffentlicht, eben weil Threads und VCL nicht zusammen funktionieren:
https://github.com/jaenicke/MTCL

TERWI 12. Jul 2018 11:14

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

Zitat von jaenicke (Beitrag 1406973)
...Beides ist aber aus einem Thread heraus verboten.

Gut, sei es einfach eben mal so.
Allerdings - siehe #20 - scheint es ja zu funktionieren. Auch
Delphi-Quellcode:
Image1.Picture.Assign(BitMap);
geht.
X andere Versuche mit Draw, CopyRect, BrushCopy auf (irgendein) Canvas funzen nicht, bzw. nur (sehr ) kurz.

Und:
Das Geflacker scheint offensichtlich eine ganz andere Ursache zu haben -> nämlich in der "Malerei" der Ursprungs-Bitmap, also FBMOSD.

Die Katze mal aus dem Sack gelassen:
Das ganze ist/wird ein DVB-Teletext-Parser, der etwas flotter, universeller mit ein paar extra Features sein soll.
Zur Zt. fliegen da noch etwa bis zu 20 BitMaps/s an die OSD, weil der Decoder noch nicht optimiert ist, bzw. noch Fehler im Detail stecken.
Durch Fehlinterpretation von Steuerzeichen kommt es daher unregelmäßig zu diesen "Flashes", wenn mit clWHite das BitMap gelöscht wird.
Ein Eigentor .....

Nun mal schauen, wie es mit dem schreiben der BM direkt in den Video-Renderer klappt, das richtige OSD also.

Vergessen:
Ich hab testweise den ParserThread rausgenommen, nun läuft alles "straight" aus der OnTSReceive Methode.
Effekt: (Erwartungsgemäß) Genau das gleiche Geflacker wie mit Parser.
Es lieht also nicht am Thread.

jaenicke 12. Jul 2018 11:56

AW: Bitmap.Canvas -> Form.Canvas ... nix zu sehen
 
Das Flackern liegt an der Art zu zeichnen. Wenn du TImage benutzt, wirst du das auch nicht wegbekommen. Das geht wirklich nur indem du im OnPaint selbst zeichnest. Damit lässt sich das weitgehend unter Kontrolle bekommen.

Viel sinnvoller wäre aber eine hardwarebeschleunigte Herangehensweise. Dann ist das ganze nicht so CPU lastig und flackert auch nicht. Delphi 2009 bietet da allerdings leider noch nichts direkt, da brauchst du externe Bibliotheken.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:08 Uhr.
Seite 1 von 2  1 2      

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