2009-04-27 4 views
4

Dies ist eine meiner ersten Ausgaben. Immer wenn ich das Programm verlasse, dauert das Schließen von tcpClient.Connect() immer. Ich habe eine Menge Dinge ausprobiert, und keiner von ihnen scheint zu funktionieren.C# Wie kann ich einen tcpClient.Connect() - Prozess stoppen, wenn ich bereit bin, das Programm zu beenden? Es sitzt nur für 10 Sekunden!

Werfen Sie einen Blick auf den Thread CreateConnection(), wenn der Client noch nicht verbunden ist ... und ich schließe das Programm, dauert es ewig zu schließen. Wenn es verbunden ist, schließt es sofort. Ich weiß, dass dies mit einer Art Timeout-Trick gemacht werden kann, aber ich habe ein paar ausprobiert und keiner von ihnen hat funktioniert.

Bitte geben Sie ein Codebeispiel an, wenn Sie können.

Gibt es auch ein gutes Tutorial für C# beim Lesen/Schreiben der tatsächlichen Bytes mit einem Puffer anstelle dieser Version, die nur masterServer.writeLine() und masterServer.readline() tut oder beide sind genauso effizient ?

Wenn Sie etwas anderes sehen, um mir zu helfen, dies zu verbessern ... auf alle Fälle, gehen Sie voran. Ich versuche mir selbst beizubringen, wie das geht, und ich habe keine Hilfe, also lass mich nicht weiter falsch machen, wenn du es siehst !!! Danke Leute!

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Net; 
using System.Net.Sockets; 
using System.Threading; 
using System.IO; 

namespace RemoteClient 
{ 
    public partial class Form1 : Form 
    { 
     private int MyPort = 56789; 
     private IPAddress myIp = IPAddress.Parse("210.232.115.79"); 
     private IPAddress serverIp = IPAddress.Parse("72.216.18.77"); // Master Server's IP Address 
     public static TcpClient masterServer = new TcpClient(); 

     private StreamWriter responseWriter; 
     private StreamReader commandReader; 

     private Thread connectionThread; 
     private Thread commandsThread; 

     private bool RequestExitConnectionThread { get; set; } 

     private delegate void AddMessageDelegate(string message, int category); 
     private delegate void ConnectedDelegate(); 

     private bool isConnected { get; set; } 

     public Form1() 
     { 
      InitializeComponent(); 
      isConnected = false; 
     } 

     private void LogMessage(string message, int category) 
     { 
      if (category == 1) 
      { 
       ListViewItem item = new ListViewItem(message); 
       item.BackColor = Color.LightGreen; 
       item.UseItemStyleForSubItems = true; 
       Log.Items.Add(item).SubItems.Add(DateTime.Now.ToString()); 
      } 
      if (category == 2) 
      { 
       ListViewItem item = new ListViewItem(message); 
       item.BackColor = Color.Orange; 
       item.UseItemStyleForSubItems = true; 
       Log.Items.Add(item).SubItems.Add(DateTime.Now.ToString()); 
      } 
      if (category == 3) 
      { 
       ListViewItem item = new ListViewItem(message); 
       item.BackColor = Color.Yellow; 
       item.UseItemStyleForSubItems = true; 
       Log.Items.Add(item).SubItems.Add(DateTime.Now.ToString()); 
      } 
      if (category == 0) 
      { 
       Log.Items.Add(message).SubItems.Add(DateTime.Now.ToString()); 
      } 
     } 

     private void Connected() 
     { 
      LogMessage("Found and Accepted Master Server's connection. Waiting for reply...",1); 
      Status.Text = "Connected!"; 
      Status.ForeColor = Color.Green; 

      commandsThread = new Thread(new ThreadStart(RecieveCommands)); 

      sendClientInfo(); 
     } 

     private void exitButton_Click(object sender, EventArgs e) 
     { 
      Disconnect(); 
      exitButton.Enabled = false; 
      exitButton.Text = "Closing..."; 

      if (connectionThread != null) 
      { 
       while (connectionThread.IsAlive) 
       { 
        Application.DoEvents(); 
       } 
      } 

      this.Close(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      Connect(); 
     } 

     private void Disconnect() 
     { 
      RequestExitConnectionThread = true; 

      if (masterServer != null) 
       masterServer.Close(); 

      if (connectionThread != null) 
       connectionThread.Abort(); 

      LogMessage("Closing Client. Please wait while Program threads end.", 2); 
     } 

     private void Disconnected() 
     { 
      Status.Text = "Disconnected"; 
      Status.ForeColor = Color.Red; 
      Connect(); 
     } 

     private void Connect() 
     { 
      LogMessage("Attempting to connect to Master Server...", 1); 

      connectionThread = new Thread(new ThreadStart(CreateConnection)); 
      connectionThread.Start(); 
     } 

     private void CreateConnection() 
     { 
      int i = 1; 
      bool success = false; 

      while (!success) 
      { 
       try 
       { 
        using (masterServer = new TcpClient()) 
        { 
         IAsyncResult result = masterServer.BeginConnect(serverIp, MyPort, null, null); 
         success = result.AsyncWaitHandle.WaitOne(1000, false); 
        } 

        if (success) 
        { 
         BeginInvoke(new ConnectedDelegate(this.Connected), new object[] {}); 
         break; 
        } 
        else 
        { 
         Thread.Sleep(2000); 
         BeginInvoke(new AddMessageDelegate(LogMessage), new object[] { "Connection Retry # " + i.ToString() + ". Master Server hasn't been started yet.", 3 }); 
        } 
       } 
       catch 
       { 
        MessageBox.Show("Error!"); 
       } 
       i++; 
      } 

     } 

     private void RecieveCommands() 
     { 
      MessageBox.Show("Hello!"); 
      commandReader = new StreamReader(masterServer.GetStream()); 

      string CommandResponse = commandReader.ReadLine(); 
      string Command = null; 

      if (CommandResponse != null) 
       MessageBox.Show("Recieved Command that was NOT null!"); 

      if (CommandResponse != null) 
      { 
       MessageBox.Show("Recieved null response!"); 
       BeginInvoke(new AddMessageDelegate(LogMessage), new object[] { "Disconnected From Master Server. Reason: Recieved Null response.", 1 }); 
       Disconnected(); 
      } 
      else if (CommandResponse.StartsWith("0")) 
      { 
       MessageBox.Show("Recieved 0 as a response!"); 
       Command = CommandResponse.Substring(2).Trim(); 

       isConnected = false; 
       BeginInvoke(new AddMessageDelegate(LogMessage), new object[] { "Disconnected From Master Server. Reason: " + Command, 1 }); 
      } 
      else if (CommandResponse.StartsWith("1")) 
      { 
       MessageBox.Show("Recieved 1 as a response!"); 
       isConnected = true; 
       BeginInvoke(new AddMessageDelegate(LogMessage), new object[] { "Connected to Master Server Successfully.", 1 }); 
      } 
     } 


     //************************** RESPONSE'S BELOW HERE ************************* \\ 

     private void sendClientInfo() 
     { 
      responseWriter = new StreamWriter(masterServer.GetStream()); 

      responseWriter.WriteLine(myIp.ToString()); 
      responseWriter.Flush(); 
     } 

    } 
} 

Antwort

1

Hinzufügen einer Überprüfung innerhalb Ihrer Verbindung Prozess, um es zu stornieren, wenn das Programm beendet wird, sollte helfen.

Versuchen das Hinzufügen dieser in CreateConnection() in Ihrem while(!success) Schleife aber vor Ihrem try Block:

if(RequestExitConnectionThread) 
{ 
    break; 
} 

Hier ist ein Beispiel eines asynchronen Beginconnect() -Aufruf:

myTcpClient.BeginConnect("localhost", 80, OnConnect, null); 

OnConnect Funktion:

public static void OnConnect(IAsyncResult ar) 
{ 
    // do your work 
} 
+0

In Ordnung, krank hinzufügen, dass in. Ich wusste bereits, dass es aufhören würde. Aber das Problem ist masterServer.Connect() Sobald es startet, sitzt es für etwa 10 Sekunden. Wenn Sie versuchen, den Programm-Debugger zu beenden, friert es einfach ein – OneShot

+0

Oh, meinst du masterServer.BeginConnect()? In diesem Fall verwenden Sie den Callback-Parameter von BeginConnect(), um die asynchrone Funktionalität zu erhalten. Ich werde meine Antwort aktualisieren, um diesen Code einzuschließen. –

5

Verbindung mit Timeout von 2000 ms ect:

AutoResetEvent connectDone = new AutoResetEvent(false); 
TcpClient client = new TcpClient(); 
client.BeginConnect(
    "127.0.0.1", 80, 
    new AsyncCallback(
     delegate(IAsyncResult ar) { 
      client.EndConnect(ar); 
      connectDone.Set(); 
     } 
    ), client 
); 
if(!connectDone.WaitOne(2000)) { 
    Console.WriteLine("network connection failed!"); 
    Environment.Exit(0); 
} 
Stream stream = client.GetStream(); 
8

Sorry, nachdem sie die Prüfung: nein, es ist nicht ein asynchrones Waithandle nicht verwendet, blockiert sie den Prozess :(

ich diese Lösung bevorzugen, die Blöcke auch der Prozess sondern nur durch den Zeitraum, den Sie angeben, in diesem Fall 5 Sekunden:

using (TcpClient tcp = new TcpClient()) 
{ 
    IAsyncResult ar = tcp.BeginConnect("127.0.0.1", 80, null, null); 
    System.Threading.WaitHandle wh = ar.AsyncWaitHandle; 
    try 
    { 
     if (!ar.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5), false)) 
     { 
      tcp.Close(); 
      throw new TimeoutException(); 
     } 

     tcp.EndConnect(ar); 
    } 
    finally 
    { 
     wh.Close(); 
    } 
} 

von: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/2281199d-cd28-4b5c-95dc-5a888a6da30d

Das folgende Beispiel verwenden sowohl Asynchron-Verbindung und async tim Kontrolle:

var tcp = new TcpClient(); 
var ar = tcp.BeginConnect(Ip, Port, null, null); 
Task.Factory.StartNew(() => 
{ 
    var wh = ar.AsyncWaitHandle; 
    try 
    { 
     if (!ar.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5), false)) 
     { 
      // The logic to control when the connection timed out 
      tcp.Close(); 
      throw new TimeoutException(); 
     } 
     else 
     { 
      // The logic to control when the connection succeed. 
      tcp.EndConnect(ar); 
     } 
    } 
    finally 
    { 
     wh.Close(); 
    } 
}); 
+1

Ich fand auch das oben genannte besser zu arbeiten. – Beyers

+0

Lösung oben blockiert immer noch Prozess in meinem VS2010-Testprogramm. – MojoDK

+0

@MojoDK ja, tut es. Ich werde diesen Beitrag aktualisieren. – JoanComasFdz