C# 如何在我准备好结束程序时停止 tcpClient.Connect() 进程?它只是坐在那里大约 10 秒钟!
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/795574/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# How do I stop a tcpClient.Connect() process when i'm ready for the program to end? It just sits there for like 10 seconds!
提问by OneShot
This is one of my first issues. Whenever I exit out the program, tcpClient.Connect() takes forever to close. I've tried a ton of things, and none of them seem to work.
这是我的首要问题之一。每当我退出程序时, tcpClient.Connect() 就会永远关闭。我已经尝试了很多东西,但它们似乎都不起作用。
Take a look at the CreateConnection() thread, if the client isn't connected yet... and I close the program, it takes forever to close. If it IS connected, it closes immediately. I know this can be done with some kind of timeout trick, but i've tried a few and none of them worked.
看一下 CreateConnection() 线程,如果客户端还没有连接……而我关闭程序,它需要永远关闭。如果它已连接,它会立即关闭。我知道这可以通过某种超时技巧来完成,但我已经尝试了一些,但都没有奏效。
Please provide a code example if you can.
如果可以,请提供代码示例。
Also, is there any good tutorial out there for C# on reading/writing the actual bytes with a buffer instead of this version that just does masterServer.writeLine() and masterServer.readline() or are they both just as efficient?
此外,是否有关于 C# 使用缓冲区读取/写入实际字节的好教程,而不是仅执行 masterServer.writeLine() 和 masterServer.readline() 的这个版本,或者它们都同样有效?
If you see anything else to help me improve this... by all means, go ahead. I'm trying to teach myself how to do this and I have no help, so don't let me go on doing something wrong if you see it!!! Thanks guys!
如果您看到其他任何东西可以帮助我改进这一点……无论如何,请继续。我正在尝试自学如何做到这一点,但我没有任何帮助,所以如果您看到它,请不要让我继续做错事!!!谢谢你们!
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();
}
}
}
采纳答案by Steven Richards
Adding a check within your connection process to cancel it if the program is exiting should help.
如果程序正在退出,则在连接过程中添加检查以取消它应该会有所帮助。
Try adding this in CreateConnection()
inside your while(!success)
loop but before your try
block:
尝试在添加此CreateConnection()
您的内部while(!success)
循环,但您之前try
块:
if(RequestExitConnectionThread)
{
break;
}
Here's an example of an asynchronous BeginConnect() call:
以下是异步 BeginConnect() 调用的示例:
myTcpClient.BeginConnect("localhost", 80, OnConnect, null);
OnConnect function:
OnConnect 函数:
public static void OnConnect(IAsyncResult ar)
{
// do your work
}
回答by Steven Richards
connect with timeout of 2000 ms:
连接超时为 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();
回答by JoanComasFdz
Sorry, after testing it: NO, it does not use an async waithandle, it blocks the process :(
抱歉,经过测试:不,它不使用异步等待句柄,它会阻止进程:(
I prefer this solution, which also blocks the process but only by the period you specify, in this case 5 seconds:
我更喜欢这个解决方案,它也会阻止进程,但只能按您指定的时间段进行,在本例中为 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
The following example uses both async connection and async timeout control:
以下示例同时使用异步连接和异步超时控制:
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();
}
});