Autor Beitrag
cometosin
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Fr 22.01.10 18:11 
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:

ausblenden volle Höhe 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;
        }


Zuletzt bearbeitet von cometosin am Mi 27.01.10 12:36, insgesamt 2-mal bearbeitet
JüTho
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2021
Erhaltene Danke: 6

Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
BeitragVerfasst: 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 Threadstarter
Hält's aus hier
Beiträge: 3



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1012
Erhaltene Danke: 24

Windows XP
C#, Visual Studio
BeitragVerfasst: 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 Threadstarter
Hält's aus hier
Beiträge: 3



BeitragVerfasst: 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:
ausblenden volle Höhe 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;

            //Dummy Connection Trick für WaitForConnection
            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);

                    // Warte auf Verbindung von einem Client
                    pipeServer.WaitForConnection();
    
                    listOfPipes.Add(pipeServer);                    
                    if (stopFlag) break;

                    Thread handleStream = new Thread(new ParameterizedThreadStart(ReadStream));
                    handleStream.IsBackground = true;
                    handleStream.Start(pipeServer);

                }
                // Ausnahmen behandeln, wenn die Pipe unverbunden oder unbrauchbar ist.
                catch (IOException e)
                {
                    Console.Write(e.Message);
                }
            }          
        }

        public void ReadStream(object pipeServerObject)
        {
            using (NamedPipeServerStream serverPipe =((NamedPipeServerStream)pipeServerObject))
            {
                // Speichert die Threads in einer Liste um sie beim Stoppen abzubrechen
                listOfReadingThreads.Add(Thread.CurrentThread);
                
                while (!stopFlag)
                {
                    byte[] buffer = new byte[1024];
                    result = serverPipe.BeginRead(buffer, 01024, callBack, buffer);

                    // Terminiert Thread wenn der Client die Verbindung trennt
                    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)
        {
            //Weiß jemand was man hier tun soll?
        }


So sieht der Client aus (ist nur zum Testen und daher nicht sauber)
ausblenden volle Höhe 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.