Benutzer mit den meisten Antworten
Server - Socket - Thread Probleme

Frage
-
Hallo,
ich habe folgende Struktur.Einen Server - Thread
Da empfange ich die Daten als String.
Diese übergebe ich einer Read Funktion.
Diese wiederum löst einen Event aus, an ein anderes Objekt.
Dieses Objekt entscheidet dann was zu tun ist.Jetzt kommen teils Exceptions bezgl. Thread.
Was kann ich tun, dass der empfangene Inhalt im korrekten Thread empfangen wird.
Was muss ich machen?
Invoke, da komme ich nicht weiter und benötige Unterstützung.Das Objekt MES beihaltet den BUS (Socketverbindung)
Daten kommen rein
ReadEvent (über Socket)
Switch
case 1: Write (Antwort wird gesendet)
Danke + Grüße Andreas
public override void Read(string data, int size, int bytesRead) { int iExecThread = System.Threading.Thread.CurrentThread.ManagedThreadId; System.Diagnostics.Trace.WriteLine("BUSSOCKET Read Thread ID " + iExecThread.ToString()); System.Diagnostics.Trace.WriteLine(data); EventHandlerContentReceived(data); } public override void Init() { int iExecThread = System.Threading.Thread.CurrentThread.ManagedThreadId; System.Diagnostics.Trace.WriteLine("BUSSOCKET Init Thread ID " + iExecThread.ToString()); public override void Read(string data, int size, int bytesRead) { int iExecThread = System.Threading.Thread.CurrentThread.ManagedThreadId; System.Diagnostics.Trace.WriteLine("BUSSOCKET Read Thread ID " + iExecThread.ToString()); System.Diagnostics.Trace.WriteLine(data); EventHandlerContentReceived(data); } BUSSOCKET Init Thread ID 10 BUSSOCKET ReceiveHandler Thread ID 17 try { buffer = new byte[maxBuffer]; received = socket.Receive(buffer); if (received == 0) { if (socket != null) socket.Close(); if (tcpListener != null) tcpListener.Stop(); } UTF8Encoding encoding = new UTF8Encoding(); empfangen = encoding.GetString(buffer, 0, received); System.Diagnostics.Trace.WriteLine("Vom Client empfangen : \"" + empfangen + "\""); int iExecThread = System.Threading.Thread.CurrentThread.ManagedThreadId; System.Diagnostics.Trace.WriteLine("BUSSOCKET ReceiveHandler Thread ID " + iExecThread.ToString()); Read(empfangen, 44, 22);
- Bearbeitet Andreas Bauer2 Donnerstag, 24. Februar 2011 16:59 Format
Antworten
-
Hallo Andreas,
kannst Du mir denn Dein Projekt nicht einfach zukommen lassen?
Eh ich alle momentan nicht geposteten Teile als Vermutung annehme ist es denke ich so besser.
Und ja - auch ohne Forms würde ich das gerne mit Neuverbinden machen - am besten, der Benutzer muss so wenig wie möglich (nötig) tun. Am besten noch den Server automatisch "finden" (etwa mit WS-Discovery, natürlich sehr einfach mit WCF 4.0)
PostAddFranksSeitePunktDE
ciao Frank- Als Antwort markiert Andreas Bauer2 Donnerstag, 3. März 2011 20:12
Alle Antworten
-
Hallo Andreas,
> Jetzt kommen teils Exceptions bezgl. Thread.
Könnte an folgendem liegen: [Illegal Cross Thread Call]
http://www.yoda.arachsys.com/csharp/threads/winforms.shtml
ich denke, es ist aber vorteilhaft, wenn Du ein kleines minimales Projekt zur Verfügung stellst, wo der Fehler reproduzierbar ist. Ggf. auch an meine private Mail Adresse PostAddFranksSeitePunktDe.
> Was kann ich tun, dass der empfangene Inhalt im korrekten Thread empfangen wird.
Normalerweise geht das über Invoke etc.
[Threadsicheres Aufrufen von Windows Forms-Steuerelementen]
ciao Frank- Als Antwort vorgeschlagen Robert BreitenhoferModerator Donnerstag, 3. März 2011 10:22
-
Hallo Frank,
ja Du hast wieder Recht. Das Projekt ist schwierig. Herauszukapseln auch.
http://www1.minpic.de/bild_anzeigen.php?id=139253&key=4033957&ende
Hauptsächlich kommt es vor, wenn ich was empfange, je nachdem was ich empfange UI Controls update.
Das darf ich wohl nicht.
Wie schon mal gesagt ich brauche Deine Klasse als Server. Vielleicht siehst Du was. Ich habe es adaptiert, aber irgendwas scheint falsch zu sein.
Suche bitte nach dem /// HIER KNALLT ES!!!!!! Kannst Du mal das und Deiner Serverklasse anschauen. Für den Server brauche ich kein UI,
wie in Deinem Beispiel.
Read sendet dann einen Event an die logische Klasse, wo der Inhalt ausgewertert wird.
public override void Read(string data, int size, int bytesRead)
{
int iExecThread = System.Threading.Thread.CurrentThread.ManagedThreadId;
System.Diagnostics.Trace.WriteLine("BUSSOCKET Read Thread ID " + iExecThread.ToString());
System.Diagnostics.Trace.WriteLine(data);
EventHandlerContentReceived(data);
}void Bussystem_EvHaContentReceived(object sender, NotifyEventArgs e) { int iExecThread2 = System.Threading.Thread.CurrentThread.ManagedThreadId; string toAnalysis = e.NotifyMessage; //throw new NotImplementedException(); // System.Windows.Forms.MessageBox.Show(toAnalysis, "Test" ); if (toAnalysis == "WorkingPos") { //WorkingPos2(); State = StateProcessWorkflow.PanelAtWorkingPos; //string s1 = ssssss_111(); Bussystem.Write("TestAntwort", 55); } }
Read sendet einen Event an das UserInterface.
void BMES_EvHaStateOfMES(object sender, NotifyEventArgs e) { //txtStateMES.Text = e.NotifyMessage; /// HIER KNALLT ES!!!!!! }
Klasse Empfang
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; using System.Threading; using System.Diagnostics; using RCommunication.Definitions.Core; //using RCommunication.Implementations.MES.OpCon.Core; //using RCommunication.Implementations.MES.OpCon; namespace RCommunication.Implementations.BUS.Socket.Core { public class BUSSocket : BaseBUS { Properties.Settings Props = Properties.Settings.Default; System.Net.Sockets.Socket socket; TcpListener tcpListener; const int maxBuffer = 100; Thread thread; /// <summary>Um den Server sauber unterbrechen zu können. /// Hiermit wird signalisiert, dass der Thread beenden soll.</summary> ManualResetEvent threadStopEvent = new ManualResetEvent(false); public override void Close() { //if (socket != null) // socket.Close(); //if (tcpListener != null) // tcpListener.Stop(); threadStopEvent.Set(); Thread.Sleep(50); while (thread.IsAlive) Thread.Sleep(10); if (socket != null) socket.Close(); if (tcpListener != null) tcpListener.Stop(); Environment.Exit(0); } public override void Init() { NeuVerbinden(); int iExecThread = System.Threading.Thread.CurrentThread.ManagedThreadId; System.Diagnostics.Trace.WriteLine("BUSSOCKET Init Thread ID " + iExecThread.ToString()); try { thread = new Thread(new ThreadStart(Execute)); thread.Start(); } catch (Exception exp) { // System.Diagnostics.Trace.WriteLine(exp.Message); } } private void NeuVerbinden() { IPAddress ipAdresse = null; try { GetIpAdresse(ref ipAdresse, Dns.GetHostName()); tcpListener = new TcpListener(ipAdresse, Props.Port); tcpListener.Start(); } catch (Exception exp) { System.Diagnostics.Trace.WriteLine("Beim Versuch der Auflösung der Addresse: " + ipAdresse.ToString() + " enstand folgender Fehler:\r\n" + exp.Message); return; } } ~BUSSocket() { } //void Read(string msg) //{ // txtMeldung.Invoke(new ServerTextCallback(ServerText), // new object[] { msg + "\r\n" }); // Thread.Sleep(5); //} //public delegate void ServerTextCallback(string text); //void ServerText(string text) //{ // EventHandlerContentReceived(text); //} public override void Read(string data, int size, int bytesRead) { int iExecThread = System.Threading.Thread.CurrentThread.ManagedThreadId; System.Diagnostics.Trace.WriteLine("BUSSOCKET Read Thread ID " + iExecThread.ToString()); System.Diagnostics.Trace.WriteLine(data); EventHandlerContentReceived(data); } public override void Write(string data, int size) { System.Diagnostics.Trace.WriteLine(data); //EvHaContentReceived(data); UTF8Encoding encoding = new UTF8Encoding(); // string toSend = "ACK"; socket.Send(encoding.GetBytes(data)); System.Diagnostics.Trace.WriteLine("\r\nSende \"" + data + "\" - Meldung"); } private IPAddress GetIpAdresse(ref IPAddress ipAdresse, string hostName) { IPAddress[] ipAdressen = Dns.GetHostEntry(hostName).AddressList; foreach (IPAddress ip in ipAdressen) { if (ip.AddressFamily == AddressFamily.InterNetwork) { ipAdresse = ip; break; } } if (ipAdresse == null) throw new Exception("Keine IPV4-IP auflösbar."); return ipAdresse; } private void Execute() { System.Diagnostics.Trace.WriteLine("Der Server ist gestartet auf Port : " + Props.Port); System.Diagnostics.Trace.WriteLine("Der lokale Endpunkt ist :" + tcpListener.LocalEndpoint); System.Diagnostics.Trace.WriteLine("Warte auf Verbindung eines Clients ..."); while (!this.threadStopEvent.WaitOne(0, true)) { Thread.Sleep(0); try { if (tcpListener.Pending()) { socket = tcpListener.AcceptSocket(); System.Diagnostics.Trace.WriteLine("Client-Verbindung akzeptiert von: " + socket.RemoteEndPoint); new Thread(new ThreadStart(ReceiveHandler)).Start(); } } catch (Exception e) { //"Der Client wurde zum Beispiel geschlossen" -> Neuverbinden System.Diagnostics.Trace.WriteLine(e.Message); } } } void ReceiveHandler() { int received = 0; byte[] buffer; string empfangen; do { try { buffer = new byte[maxBuffer]; received = socket.Receive(buffer); if (received == 0) { if (socket != null) socket.Close(); if (tcpListener != null) tcpListener.Stop(); return; // Application.Exit(); return; // wenn der Client "" sendet, soll der Server beenden. (nur als Beispiel) } UTF8Encoding encoding = new UTF8Encoding(); empfangen = encoding.GetString(buffer, 0, received); System.Diagnostics.Trace.WriteLine("Vom Client empfangen : \"" + empfangen + "\""); int iExecThread = System.Threading.Thread.CurrentThread.ManagedThreadId; System.Diagnostics.Trace.WriteLine("BUSSOCKET ReceiveHandler Thread ID " + iExecThread.ToString()); if ( empfangen.Length > 1 ) Read(empfangen, 44, 22); //string toSend = "ACK"; //socket.Send(encoding.GetBytes(toSend)); //System.Diagnostics.Trace.WriteLine("\r\nSende \"" + toSend + "\" - Meldung"); } catch (Exception exp) { System.Diagnostics.Trace.WriteLine(exp.Message); } } while (received != 0); } } }
-
Hallo Frank,
das Problem ist vielleicht gegenüber Deinem Beispiel.
Ich empfange eine Anfrage vom Client. Sende nicht sofort eine Antwort.
Diese gilt es woanders zu analysieren. Je nachdem muss ich was senden und den Status visualisieren.
Alles muss natürlich im Hintergrund laufen, deshalb richtig Thread für den Server.
Du hast wie Immer! Recht. Das geht!
void BMES_EvHaStateOfMES(object sender, NotifyEventArgs e) { txtStateMES.Invoke(new Action<string>(s => { txtStateMES.Text = s; }), "meine Info" + e.NotifyMessage); }
http://dzaebel.net/ControlInvoke.htm
4 Bitten an Dich
1) Kannst Du mir das in wenigen Worten erklären, warum das ohne Meldung geht? Was passiert da?
2) Die Variante - Funktionszeiger
textBox1.Invoke(new UpdateTextCallback(this.UpdateText);
public delegate void UpdateTextCallback(string text);
private void UpdateText(string text)
{
textBox1.Text = text;
}3 ) Ohne Invoke, mit BackgroundWorker, da macht der Backgound alles, oder? Da wird ja der Textbox nichts großes gemacht, eigentlich normal.
4) GANZ WICHTIG, habe ich Deinen Server korrekt gekapselt ohne UserInterface, ohne Forms.
Bitte querchecken und Danke.
Grüße Andreas
- Bearbeitet Andreas Bauer2 Samstag, 26. Februar 2011 20:13 Format
-
Hallo Andreas,
kannst Du mir denn Dein Projekt nicht einfach zukommen lassen?
Eh ich alle momentan nicht geposteten Teile als Vermutung annehme ist es denke ich so besser.
Und ja - auch ohne Forms würde ich das gerne mit Neuverbinden machen - am besten, der Benutzer muss so wenig wie möglich (nötig) tun. Am besten noch den Server automatisch "finden" (etwa mit WS-Discovery, natürlich sehr einfach mit WCF 4.0)
PostAddFranksSeitePunktDE
ciao Frank- Als Antwort markiert Andreas Bauer2 Donnerstag, 3. März 2011 20:12