Entwickler-Ecke
Sonstiges (.NET) - C# Thread Management bei blockierenden Befehlen [Erledigt]
cometosin - Fr 22.01.10 18:11
Titel: C# Thread Management bei blockierenden Befehlen [Erledigt]
Hallo Zusammen,
so ich bin neu hier und hoffe dass ihr mir helfen könnt.
Mit C# kenn ich mich schon ein wenig aus aber Profi bin ich halt nicht.
Also zu meinem Problem:
Ich habe es mit NamedPipes zu tun und benutze dafür System.IO.Pipes. Mein Problem ist dass ich einen Thread für das entgegenehmen der Clients habe
und dieser bei der Funktion WaitForConnection blockiert. Ist ja auch richtig so. Aber wie kann ich diesen Thread dann beim beenden des Programms beenden?
Bin für alle Ratschläge dankbar.
Mfg cometosin
So hier mal mein erster Entwurf:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53:
| class NamedPipeServer {
public delegate void MessageReceived(string message); public event MessageReceived messageEvent;
private Thread waitForConnection = null; private bool flag = true; private List<NamedPipeServerStream> pipes = new List<NamedPipeServerStream>();
public bool Start() { waitForConnection = new Thread(new ThreadStart(ThreadStartServer)); waitForConnection.Start(); return true; } public void ThreadStartServer() { while (true) { NamedPipeServerStream pipeStream = new NamedPipeServerStream("LogonPipe"); pipeStream.WaitForConnection(); Thread read = new Thread(new ParameterizedThreadStart(readFromStream)); pipes.Add(pipeStream); } }
public void readFromStream(object objPipestream) { NamedPipeServerStream pipeStream = (NamedPipeServerStream)objPipestream; StreamReader sr = new StreamReader(pipeStream);
while (flag) { string message = sr.ReadLine(); if (messageEvent != null) { messageEvent(message); } } sr.Close(); pipeStream.Close(); }
public bool CloseConnections() { flag = false; waitForConnection.Abort(); return true; } |
JüTho - Fr 22.01.10 20:00
1½ Stunden Wartezeit ist sehr wenig für einen zweiten Post zum gleichen Thema. Übrigens kann auch hier C#-Code als solcher markiert werden (und nicht als Zitat); das kannst du noch berichtigen: Öffne deinen Beitrag nochmals mit dem Schere-Button, den Code-Auszug markieren, unter "Bereiche" in der ComboBox C# auswählen, mit dem Plus-Button bestätigen, mit "Absenden" speichern. Danke! Jürgen
cometosin - Fr 22.01.10 20:14
Entschuldigung das mit dem Post in anderen Foren hab ich leider überlesen.
Kommt nicht wieder vor.
Edit: Habe es zum löschen gemeldet
Sry cometosin
danielf - Mo 25.01.10 11:19
Hallo cometosin,
das Handling von Threads macht man in C# wie in anderen Programmiersprachen auch ;)
Du hast die Klasse in einen Thread gelegt, weil du 1) auf eingehende Verbindungen wartest aber Parallel etwas anderes machen möchtest und 2) eine Endlosschleife um dies zu wiederholen. Möchtest du also den Thread beenden, muss du das Warten und die Endlosschleife beenden --> dann läuft der Thread aus.
Sprich anstatt einer Endlosschleife mit while(true) machst du eine Schleife mit einer bool Klassenvariable (z.B. _run). Dazu eine öffentliche Stop-Methode (zum Beispiel public void Stop() ;) ) in dieser du dann die Klassenvariable auf false stellst. Dann hast du noch das Problem, dass WaitForConnection blockiert. Ich meine diese Funktion ist überladen und du kannst einen TimeOut angeben. Zuletzt musst du die noch in einer Liste oder so merken, welche Klassen/Threads du aktiv/erstellt hast. Beim Beenden gehst du dann durch die Liste durch und Stoppst alle.
Gruß Daniel
cometosin - Mo 25.01.10 21:33
Hey danielf,
danke für die Tips. Leider hat sich mein Problem etwas verlagert.
Das mit dem Beenden der Threads habe ich geschafft.
Bei WaitForConnection() habe ich mit einem kleinen Trick auskommen müssen,
da es hier kein Timeout gibt. (zumindest nicht wie bei TCP oder so, vllt bin ich ach blind)
Mein Problem ist das ich die bidirektionale Kommunikation also PipeDirection.InOut
nicht hinbekomme. Habe jetzt versucht über die BeginRead und BeginWrite Methoden
weiterzukommen aber leider bisher nur mit geringem Erfolg.
(Wenn ich beim Client den Read-Thread nicht starte, kann ich von Client zu Server
Kommunizieren.)
Ist jetzt ein bisschen viel Code aber ich versuche es mal vllt findet
ja doch jemand meine(n) Fehler.
Code für den Server:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122:
| private AsyncCallback callBack = new AsyncCallback(ProcessReadMessage); private AsyncCallback callWrite = new AsyncCallback(ProcessWrittenMessage); private bool stopFlag = false; private IAsyncResult result = null; private IAsyncResult wresult = null; private List<NamedPipeServerStream> listOfPipes = null; private List<Thread> listOfReadingThreads = null; private NamedPipeServerStream pipeServer = null; private NamedPipeClientStream abortClient = null; public bool Stop() { stopFlag = true;
abortClient = new NamedPipeClientStream("TestPipe"); abortClient.Connect(); abortClient.Close(); foreach (Thread temporaryThread in listOfReadingThreads) { temporaryThread.Abort(); } return true; }
public bool Start() { stopFlag = false; connectionThread = new Thread(new ThreadStart(ListenForConnection)); connectionThread.IsBackground = true; listOfPipes = new List<NamedPipeServerStream>(); listOfReadingThreads = new List<Thread>(); connectionThread.Start(); listOfReadingThreads.Add(connectionThread); return true; }
public void ListenForConnection() { while (!stopFlag) { try { pipeServer = new NamedPipeServerStream("TestPipe", PipeDirection.InOut,10);
pipeServer.WaitForConnection(); listOfPipes.Add(pipeServer); if (stopFlag) break;
Thread handleStream = new Thread(new ParameterizedThreadStart(ReadStream)); handleStream.IsBackground = true; handleStream.Start(pipeServer);
} catch (IOException e) { Console.Write(e.Message); } } }
public void ReadStream(object pipeServerObject) { using (NamedPipeServerStream serverPipe =((NamedPipeServerStream)pipeServerObject)) { listOfReadingThreads.Add(Thread.CurrentThread); while (!stopFlag) { byte[] buffer = new byte[1024]; result = serverPipe.BeginRead(buffer, 0, 1024, callBack, buffer);
if (serverPipe.IsConnected) serverPipe.EndRead(result); else { break; } } } }
public bool WriteMessageThroughPipes(string message) { byte[] buffer = StringToByteArray(message);
foreach (NamedPipeServerStream temporaryPipeStreams in listOfPipes) { if (temporaryPipeStreams.CanWrite) { wresult = temporaryPipeStreams.BeginWrite(buffer, 0, buffer.Length, callWrite, buffer); temporaryPipeStreams.EndWrite(wresult); } } return true; }
private static void ProcessReadMessage(IAsyncResult result) { byte[] buffer = (byte[])result.AsyncState; string message = null; message = ByteArrayToString(buffer); int lastIndex = message.IndexOf("\0"); if (lastIndex != -1) message = message.Substring(0, lastIndex); else message = String.Empty; if (!String.IsNullOrEmpty(message)) { if (messageEvent != null) messageEvent(message); } }
private static void ProcessWrittenMessage(IAsyncResult result) { } |
So sieht der Client aus (ist nur zum Testen und daher nicht sauber)
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39:
| public Form1() { InitializeComponent(); buffer = new byte[1024]; client = new NamedPipeClientStream(".","TestPipe",PipeDirection.InOut); client.Connect(); readThread = new Thread(new ThreadStart(Read)); readThread.IsBackground = true; readThread.Start(); }
private void Sent_Click(object sender, EventArgs e) { byte [] buffer = StringToByteArray(eingabe.Text); if (client.CanWrite) { wresult = client.BeginWrite(buffer, 0, buffer.Length, callwrite, buffer); } }
private void Read() { while (true) { result = client.BeginRead(buffer, 0, buffer.Length, callback, buffer); } } static void ReadFunc(IAsyncResult result) { byte[] erg = (byte[])result.AsyncState; client.EndRead(result); }
static void processWrite(IAsyncResult result) { client.EndWrite(result); } |
Okay falls jemand hierzu mehr Erfahrung hat und ein paar Ratschläge hat nur raus damit ;-)
Vielen Dank fürs Lesen
Mfg cometosin
Edit: So hat sich alles erledigt habe eine Lösung gefunden.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!