GTKMM Gtk::TextBuffer nutzen beim Multithreading



  • Hallo allerseits, ich bin neu in dem Forum und hoffe auch Hilfe zu finden.
    Sollten Bemerkungen oder sonstiges sein nur sagen.

    Da ich nicht viel drum herum reden will komme ich gleich zum Thema.
    Schreibe eine Grafische Oberfläche mit GTKmm

    Mein vorhaben ist ein vernünftiges grafisches Terminal-Programm zu schreiben.

    In dem Terminal-Programm soll möglich sein mit einem µC (Microcontroller) über die RS232 Schnittstelle zu kommunizieren.

    Empfangene Daten sollen angezeigt werden.

    Damit mein Programm bei der Schnittstellen Kommunikation nicht einfriert nutzte ich Threads in GTKmm.

    Mein Problem ist mit dem Gtk::TextView genauer gesagt Gtk::Buffer.
    Wenn ich einen Thread laufen lasse der in den Buffer Daten reinschreibt geht das nur mit einer begrenzten Geschwindigkeit wird es zu schnell stürzt das Programm ab, hier die Fehlermeldung:

    (gtk_programm:7286): Gtk-CRITICAL **: gtk_text_layout_real_invalidate: assertion `layout->wrap_loop_count == 0' failed

    (gtk_programm:7286): Gtk-CRITICAL **: gtk_text_layout_real_invalidate: assertion `layout->wrap_loop_count == 0' failed

    (gtk_programm:7286): Gtk-CRITICAL **: gtk_text_layout_real_invalidate: assertion `layout->wrap_loop_count == 0' failed

    (gtk_programm:7286): Gtk-WARNING **: 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

    Was könnte das sein bzw. wie kann ich das umgehen?
    Da über die RS232 Schnittstelle die Daten schnell rein kommen können möchte ich das nicht über den Hauptthread laufen lassen da das Programm dann
    einfrieren würde.

    Bitte um Hilfe


  • Mod

    Du solltest die Daten nicht direkt da reinschreiben, sondern sie wo anders erstmal zwischenspeichern.
    Zwischen den Threads solltest du auch eher mit Events kommunizieren, so das nur der Hauptthread in die GUI Elemente schreiben kann.

    phlox



  • Danke für die schnelle Antwort!

    Meinst du mit Events Signal-Slot Verbindungen oder hat GTKmm eigene Events die man für so was benutzten kann?

    Tscheburator


  • Mod

    Sollte beides funktionieren, boost::signals2 ist threadsicher, bei GTK::Events müsstest du das noch abklären (afaik ja).



  • Tscheburator schrieb:

    Danke für die schnelle Antwort!

    Meinst du mit Events Signal-Slot Verbindungen oder hat GTKmm eigene Events die man für so was benutzten kann?

    Tscheburator

    Dafür nimmt man idR die sigc++ her, die ja auch von gtkmm verwendet wird 😉



  • Danke für eure antworten.
    Habe gerade noch ein Problem und zwar nutzt ich die ComboBox für die Auswahl der
    COM Schnittstelle. Die angeschlossenen COM Schnittstellen werden aus dem Registry
    ausgelesen und dort hinein gefügt. Wenn man jetzt während der Laufzeit eine
    Virtuelle Schnittstelle z.B. FTDI-Chip anklemmt möchte ich das Programm nicht
    ausschalten sondern habe ein Button hinzugefügt "Update COMx" bei Betätigung des
    Buttons wird die Registry erneut eingelesen. Und jetzt kommt das Problem.
    Bevor ich die Registry einlese will ich die ComboBox mit dem alten Inhalt löschen
    mit "Gtk::ComboBox::erase()" meine Box habe ich folgend benannt "comboBox_comx"
    daraus resultiert "comboBox_comx->erase()" hier mal der Programm teil:

    void Communication_Interface::initial_comboBox_comx()
    {
    unsigned char buffer[10];

    if(listStore_comx != NULL)
    listStore_comx->clear();

    listStore_comx = Gtk::ListStore::create(*column_record);

    comboBox_comx->set_model(listStore_comx);

    for(unsigned long int counter = 0; read_registry(counter, buffer); counter++)
    {
    Gtk::TreeRow row = *(listStore_comx->append());
    row[*treeModelColumn_name] = (char*)buffer;
    row[*treeModelColumn_value] = counter;
    }

    comboBox_comx->pack_start(*treeModelColumn_name);
    comboBox_comx->set_active(0);
    }

    Wenn ich das mache löscht er mir den Inhalt aber nicht raus sondern setzt mir
    nochmal die erkannten Schnittstellen neben den alten. Es ensteht ein misch masch!

    Was ich schon probiert habe ist das ich das ich durch das betätigen des Button eine zwei Signale/Slot Verbindungen gemacht habe. Die erste Verbindung zum
    löschen des Inhalts und die zweite zum neu einlesen, geht auch nicht.
    Nach meiner Meinung sieht das aus als ob es die ComboBox erst nach der Durchführung der ganzen Funktion neu zeichnet oder so. Weil wenn ich die Signal/Slot Verbindung zum neu einlesen weg lasse und nur die zum löschen ausführen lasse dann löscht er den Inhalt raus.

    Was kann man da machen??? 😞

    Bitte nochmal um Hilfe!
    Falls der ganze Quellcode gebraucht wird bitte mitteilen!

    Gruß
    Tscheburator



  • Entschuldigung habe ein Fehler in dem Text. Mit comboBox_comx->erase()
    ist listStore_comx->clear() gemeint. Sorry


Anmelden zum Antworten