C#当我准备好程序结束时,如何停止tcpClient.Connect()进程? 它就在那里坐了10秒钟!

这是我的第一个问题之一。 每当我退出程序时,tcpClient.Connect()都会永远关闭。 我尝试了很多东西,但似乎都没有。

看看CreateConnection()线程,如果客户端还没有连接……我关闭程序,它需要永远关闭。 如果已连接,则立即关闭。 我知道这可以通过某种超时技巧来完成,但我尝试了一些,但没有一个工作。

如果可以,请提供代码示例。

另外,C#在读取/写入实际字节时是否有任何好的教程用缓冲区而不是只有masterServer.writeLine()和masterServer.readline()的版本,或者它们都同样有效吗?

如果你看到其他任何东西可以帮助我改善这一点……无论如何,请继续。 我正在努力教自己如何做到这一点,我没有任何帮助,所以如果你看到它,不要让我继续做错事! 多谢你们!

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(); } } } 

如果程序退出,在连接过程中添加一个检查以取消它应该有所帮助。

尝试在while(!success)循环中的CreateConnection()添加它,但在try块之前:

 if(RequestExitConnectionThread) { break; } 

以下是异步BeginConnect()调用的示例:

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

OnConnectfunction:

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

对不起,测试后:不,它不使用异步等待处理,它阻止进程:(

我更喜欢这个解决方案,它也会阻止进程,但只能按你指定的时间段,在这种情况下为5秒:

 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(); } } 

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

以下示例使用异步连接和异步超时控件:

 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(); } }); 

连接超时2000毫秒:

 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();