Multithreading und LCL

Rund um die LCL und andere Komponenten
Antworten
Mathias
Beiträge: 6956
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Multithreading und LCL

Beitrag von Mathias »

Ich wollte mit Mutltithreading eine LCL-Lomponente befüllen.
Nur läuft es nicht richtig.
Es hängt sich auf, und es kommt von GTK" eine Fehlermeldung.
Lasse ich das Lines.Add weg, funktioniert es, das Writeln geht.

Code: Alles auswählen

uses
  cthreads,
...
function thread_cb(parameter: pointer): ptrint;
var
  pc: PChar absolute parameter;
begin
  Sleep(1000);  // mache etwas
  WriteLn(pc);
  Form1.Memo1.Lines.Add('blabla');
  Result := 0;
  EndThread(0);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  BeginThread(@thread_cb, PChar('Thread 1'));
  BeginThread(@thread_cb, PChar('Thread 2'));
  BeginThread(@thread_cb, PChar('Thread 3'));
  BeginThread(@thread_cb, PChar('Thread 4'));
end;
Hier noch die Fehler, welches GTK2 ausspuckt:

Code: Alles auswählen

(project1:5025): Gtk-WARNING **: 13:58:54.808: Invalid text buffer iterator: either the iterator is uninitialized, or the characters/pixbufs/widgets in the buffer have been modified since the iterator was created.
You must use marks, character numbers, or line numbers to preserve a position across buffer modifications.
You can apply tags and insert marks without invalidating your iterators,
but any mutation that affects 'indexable' buffer contents (contents that can be referred to by character offset)
will invalidate all outstanding iterators
Thread 3
Thread 2
Thread 1
Thread 4
**
Gtk:ERROR:../../../../gtk/gtktextiter.c:1779:forward_line_leaving_caches_unmodified: assertion failed: (!_gtk_text_line_is_last (new_line, real->tree))
Bail out! Gtk:ERROR:../../../../gtk/gtktextiter.c:1779:forward_line_leaving_caches_unmodified: assertion failed: (!_gtk_text_line_is_last (new_line, real->tree))
Abgebrochen (Speicherabzug geschrieben)
Ich vermute, das es mit so etwas ähnlichem zusammenhängt, wie ich mal bei einer Konsolen-Anwendung angewendet habe.
Dazuml habe ich einen Mutex gesperrt.

Code: Alles auswählen

      pthread_mutex_lock(@mutex);
      Write(Thread.index, ' ');
      pthread_mutex_unlock(@mutex);
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

paweld
Beiträge: 91
Registriert: So 11. Jun 2023, 16:01
OS, Lazarus, FPC: Lazarus trunk, FPC fixes

Re: Multithreading und LCL

Beitrag von paweld »

Wenn Sie auf Komponenten eines Formulars (Hauptthread) in Threads zugreifen wollen, müssen Sie „Synchronisieren“ verwenden: https://wiki.lazarus.freepascal.org/Mul ... se_TThread
Grüße / Pozdrawiam
paweld

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6850
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Multithreading und LCL

Beitrag von af0815 »

Die UI ist generell nicht Threadfest, war schon bei Delphi so. GUI also immer über den Hauptthread aktualisieren, Synchronize ist das eine Wahl, geht auch über Botschaften oder andere asynchrone Techniken. Je nachdem man den Thread blockieren oder nicht blockieren will.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Benutzeravatar
theo
Beiträge: 10922
Registriert: Mo 11. Sep 2006, 19:01

Re: Multithreading und LCL

Beitrag von theo »

af0815 hat geschrieben: So 27. Okt 2024, 16:22 Die UI ist generell nicht Threadfest, war schon bei Delphi so. GUI also immer über den Hauptthread aktualisieren, Synchronize ist das eine Wahl, geht auch über Botschaften oder andere asynchrone Techniken. Je nachdem man den Thread blockieren oder nicht blockieren will.
Ja. Wenn man dauernd "synchronisiert", kann das ganze Multithreading nach hinten losgehen, bzw. zur Bremse werden.
Das muss man im Auge behalten, sonst ist das Ganze nur unnötig aufwändig und fehleranfällig.

Mathias
Beiträge: 6956
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Multithreading und LCL

Beitrag von Mathias »

Dann werde ich wohl besser bei Application.ProcessMessages; bleiben.


Ich habe in meinem Code folgendes. Die message_cb ändert ein TShapes und das scheint gut zu funktionieren, mehreren Tests.
Ich nehme an, dies funktioniert auch nur, weil kein Multithreading verwendet wird.

Code: Alles auswählen

  g_signal_connect(G_OBJECT(bus), 'message::element', TGCallback(@message_cb), Self);
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6850
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Multithreading und LCL

Beitrag von af0815 »

Mathias hat geschrieben: So 27. Okt 2024, 18:10 Dann werde ich wohl besser bei Application.ProcessMessages; bleiben.
Das hält ganz einfach die Messagequeuce am Laufen. geht natürlich nur im Hauptthread. Hat nichts mit Threads am Hut.

Bei dir kann es bei gstramer zu Problemen führen, da du mit dem callback eventuell im falschen Kontext (=Thread) herauskommst. Kann durch Zufall funktionieren, muss es aber nicht. Gstreamer kann im Hintergrund natürlich Threads abspalten und dann wird es interessant. Die Frage ist, was du im Callback machst. Im einfachsten Fall schreibst du eine Message in eine Variable und das Hauptprogramm kann das asynchron rausschreiben. Es gibt einige Thread sichere Listen, wo man sowas gut machen kann, wenn es hauptsächlich in eine Richtung geht.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Antworten