[C#] Thread fehler. Ich habe kein Zugriff auf ein Objekt


ruNN0r

Erfahrenes Mitglied
#1
Hallo,
ich bin seit langem auf der suche nach einer einfachen und nicht all zu komplexen Programmierspache mit der ich mir schnell einige Tool schreiben kann um z.B. meine µC zu steuern. z.B. per RS232. Was dann wieder per Funk an alle Controller weitergeleitet wird.

Lange habe ich gesucht und bin auf C# bzw. WPF gestoßen. Da mir auch die leichte erstellung einer GUI wichtig war. Nun habe ich es geschafft und gefunden und schreibe gerade ein Tool mit dem ich einfach per RS232 Daten senden und Empfangen kann. Dazu will ich meinen COM1 Brücken so dass alles gesendete auch das empfangene ist ^^
Klappt irgendwie schon, jedoch soll er die ganze Zeit schauen ob etwas empfangen wurde und da hackts. Dazu brauche ich ja einen Thread welchen ich auch erstellt habe und dieser Führt eine Funktion aus die dann eine Endlosschleife mit abbruchvariable hat.
Klappt soweit auch ^^

Nun versuche ich jedoch auf ein Objekt zuzugreifen in dem dann die Daten ausgegeben werden soll die Empfangen wurden. Und da bekomme ich diese Fehlermeldung von Visual Studio 2010 Express:

"Der aufrufende Thread kann nicht auf dieses Objekt zugreifen, da sich das Objekt im Besitz eines anderen Threads befindet."

Irgendwie muss ich dieses Objekt doch in "meinen" Besitz bekommen können.
Ich habe schon viel gesehen mit Dispatcher und Invoke und und und. Jedoch verstehe ich die nicht und meist funktionieren die nicht weil teilweise einfach sachen davon für das Framework 3 sind und im 4 scheinbar nicht mehr vorhanden sind.

Also, vielleicht hat mal jemand eine Idee.
Natürlich hier noch Quellcode ausschnitte. Wenn die nicht reichen schicke ich auch alles aber ihr müsst euch ja nicht unnötig durch alles durchquälen.

Button gedrückt und der Thread wird gestartet
Code:
Thread t1 = new Thread(empfangen);
t1.Name = "Empf";
t1.Priority = ThreadPriority.Normal;
t1.Start();
Der Thread:
Code:
private void empfangen()
        {
            while (connection)
            {
                if (empf_klar.Dispatcher.CheckAccess())
                {
                    empf_klar.Text += "Test\n";
                }
                else
                {
                    
                }
                
            }
        }
Die Abfrage habe ich schon mal hinbekommen ;) aber wie kann ich nun das objekt empf_klar (Lableobjekt) ansprechen?

ich danke euch!
 

ruNN0r

Erfahrenes Mitglied
#3
Jo, damit gehts... Bekomme jetzt nur eine MemoryExeption weil ich es zu oft ausführe... vielleicht ist ein Textblock nicht so ganz geeignet, evtl. sollte ich ein Textfeld, wenn ich sowas finde... mal sehen. Aber es hat mir schon mal geholfen!

Achja, und danke fürs verschieben. Habe das Unterforum in .Net nicht gesehen und dachte dann reihe ich es bei C/C++ ein ^^
 

ruNN0r

Erfahrenes Mitglied
#5
ich habe nun ein textfeld draus gemacht und erweitere dies. Es ist auch etwas Konfortabler da ich es nun scrollen kann und immer der Letzte "Datensatz" angezeigt wird. Ebenfalls habe ich einen Thread.sleep(100) eingebaut. Ob der zu groß, klein oder sonst was ist, muss ich erst noch sehen... aber aktuell funktioniert es...
 
#6
Ich weiß ja nicht, was genau du mit dem Textfeld machst,
aber man könnte die älteren Sachen ja entfernen.
zB. wenns über 1MB geht den vorderen halben MB löschen.
Und die Memoryexception abfangen und im catch auch löschen.
 

ruNN0r

Erfahrenes Mitglied
#7
Ich bin noch nicht so wirklich weit in dem Thema ;)
Exceptions abfangen schaffe ich auf jeden fall :D
Ja, also das Textfeld soll die Empfangen Daten beherbergen.
Es gibt insgesamt drei davon (soll es geben...)
Für Klartext, Binärform und Hexform.
Dort steht dann sowas drin:

[08:46:22] 255
[08:46:22] 158
[08:46:22] 248

Das ist nur ein Beispiel. So kann ich dann einfach sehen was für Daten ankommen. Ebenfalls will ich Daten Senden können... klar gibt es all diese Tools schon, jedoch exakt das muss mein Späteres Programm Primär machen was für eine Spezielle Sache zugeschnitten wird. Daher versuche ich mich gerade an den Primären funktionen.

Funktioniert schon sehr gut.
So sieht meine Textbox aus:
Code:
                    <RichTextBox Margin="6,7,0,0" Name="RichTextBox2" HorizontalAlignment="Left" VerticalAlignment="Top" Width="391" Height="444">
                        <FlowDocument Name="Doc2">
                            <Paragraph Name="para2"></Paragraph>
                        </FlowDocument>
                    </RichTextBox>
So meine Verarbeitung:
Code:
                para1.Dispatcher.BeginInvoke(new Action(() => para1.Inlines.Add("[" + DateTime.Now.ToString("hh:mm:ss") + "] Hallo\n")));
                RichTextBox1.Dispatcher.BeginInvoke(new Action(() => RichTextBox1.ScrollToEnd()));

                Thread.Sleep(100);
Wie würdest du es am geschicktesten machen um die ersten Daten zu entfernen?
Also ich wüsste jetzt nicht wie ich die ersten Zeilen löschen kann...

Aber mein Rs232 funktioniert leider auch nicht... bekomme immer die Meldung dass meine Einstellungen nicht passen :( Also die Exception... habe die seperat abgefangen und Messageboxen erstellt.

Falls du mal drüber schauen magst habe ich hier die Funktion:
Der Code ist nicht der beste ist aber auch aktuell nur um mich an C# zu gewöhnen und auszuprobieren.
Code:
        //Verbindungsbutton gedrückt
        private void connect_Click(object sender, RoutedEventArgs e)
        {
            
            bool fail = false;
            if (connect_text)
            {
                try
                {
                    status_text.Text = "Verbindung wird hergestellt.";
                    status_bar.Value = 50;
                    add_aktion("Beginne Verbindungsaufbau");

                    //Port Einstellen
                    //myPort = new SerialPort(Convert.ToString(select_com.SelectionBoxItem), Convert.ToInt32(select_baud.SelectionBoxItem), Parity.None, Convert.ToInt32(databits.Text),StopBits.One);
                    myPort = new SerialPort(Convert.ToString(select_com.SelectionBoxItem));
                    
                    //Baud festelegen
                    myPort.BaudRate = Convert.ToInt32(select_baud.SelectionBoxItem);

                    //Datenbits
                    myPort.DataBits = Convert.ToInt32(databits.Text);

                    //Parität festlegen
                    if (select_paritaet.SelectedIndex == 0)
                    {
                        myPort.Parity = Parity.None;
                    }
                    else if(select_paritaet.SelectedIndex == 1)
                    {
                        myPort.Parity = Parity.Odd;
                    }
                    else if(select_paritaet.SelectedIndex == 2)
                    {
                        myPort.Parity = Parity.Even;
                    }
                    else if(select_paritaet.SelectedIndex == 3)
                    {
                        myPort.Parity = Parity.Mark;
                    }
                    else if(select_paritaet.SelectedIndex == 4)
                    {
                        myPort.Parity = Parity.Space;
                    }

                    if (select_stop.SelectedIndex == 0)
                    {
                        myPort.StopBits = StopBits.None;
                    }
                    else if (select_stop.SelectedIndex == 0)
                    {
                        myPort.StopBits = StopBits.One;
                    }
                    else if (select_stop.SelectedIndex == 0)
                    {
                        myPort.StopBits = StopBits.OnePointFive;
                    }
                    else if (select_stop.SelectedIndex == 0)
                    {
                        myPort.StopBits = StopBits.Two;
                    }
                    
                    //Port Öffnen
                    myPort.Open();
                }
                catch (System.IO.IOException)
                {
                    MessageBox.Show("Der Zustand der Ports ist nicht bekannt.\n\nMöglicher Grund:\nDieser Port existiert nicht.", "Fehler", MessageBoxButton.OK, MessageBoxImage.Hand);
                    fail = true;
                }
                catch (System.UnauthorizedAccessException)
                {
                    MessageBox.Show("Zugriff verweigert.", "Fehler",MessageBoxButton.OK,MessageBoxImage.Hand);
                    fail = true;
                }
                catch (System.ArgumentOutOfRangeException)
                {
                    MessageBox.Show("Die Eigenschaften sind Ungültig.", "Fehler", MessageBoxButton.OK, MessageBoxImage.Hand);
                    fail = true;
                }
                catch (System.ArgumentException)
                {
                    MessageBox.Show("Der Port fängt nicht mit COM an.", "Fehler", MessageBoxButton.OK, MessageBoxImage.Hand);
                    fail = true;
                }
                catch (System.InvalidOperationException)
                {
                    MessageBox.Show("Der Port ist bereits geöffnet.", "Fehler", MessageBoxButton.OK, MessageBoxImage.Hand);
                    fail = true;
                }
                catch (System.Exception ex)
                {
                    MessageBox.Show(ex.ToString(), "Unbekannter Fehler", MessageBoxButton.OK, MessageBoxImage.Hand);
                    fail = true;
                }
                finally
                {
                    if (!fail)
                    {
                        status_bar.Value = 100;
                        status_text.Text = "Verbindung hergestellt.";
                        add_aktion("Verbindung aufgebaut");
                        connect.Content = "Verbindung trennen";
                        connect_text = false;
                        connection = true;

                        Thread t1 = new Thread(empfangen);
                        t1.Name = "Empf";
                        t1.Priority = ThreadPriority.Lowest;
                        t1.Start();

                        status_bar.Value = 0;
                        //textBlock2.Text += " [" + DateTime.Now.ToString("yyyy.MM.dd - hh:mm:ss") + "]\n Verbindung zu " + Convert.ToString(select_com.SelectionBoxItem) + " hergestellt\n";

                        
                    }
                    else
                    {
                        status_text.Text = "Verbindungsaufbau fehlgeschlagen";
                        status_bar.Value = 0;
                        add_aktion("Verbindungsaufbau fehlgeschlagen");
                    }
                }
            }
            else
            {
                status_bar.Value = 50;
                status_text.Text = "Verbindung wird beendet";
                add_aktion("Verbindung wird beendet");
                connection = false;

                myPort.Close();
                status_bar.Value = 100;
                status_text.Text = "Verbindung beendet";
                status_bar.Value = 0;

                add_aktion("Verbindung beendet");

                connect.Content = "Verbinden";
                connect_text = true;

                
            }
        }
Edit:
myPort habe ich in der Klasse festgelegt:
SerialPort myPort;

Die meisten Einstellungen sind per Dropdownmenü daher auch das Selected und die Convertierung jedes mal.
 

ruNN0r

Erfahrenes Mitglied
#8
Ahh, scheinbar kein Programmierfehler direkt... habe selber nur die einstellungen falsch gewählt... aber nun geht die verbindung auch wieder...

dann werde ich mal versuchen, den Port zu brücken und daten zu Empfangen.
 

Neue Beiträge