我编写了一个简单的测试程序,使用两种不同的技术来实现您的目标,并测试您发布的确切代码。我无法重现您所描述的问题。无论我使用TcpClient
or Socket
直接调用Close()
对象上的结果导致连接操作立即完成(嗯,在完成所有异步完成、异常处理、线程同步等之后,不到 1/10 秒)
请注意,在TcpClient
案例中,TcpClient
类似乎有一个错误,它会抛出NullReferenceException
而不是(正如人们所期望的那样)ObjectDisposedException
。这似乎是因为TcpClient
设置Client
财产给null
when Close()
被调用,但随后在调用完成委托时尝试使用该值。哎呀。
这意味着在您的代码中,调用者会看到NullReferenceException
而不是Exception
你似乎想扔。但这本身似乎不会导致实际的延迟。
这是我的测试程序:
class Program
{
static void Main(string[] args)
{
_TestWithSocket();
_TestWithTcpClient();
try
{
_TestSOCode();
}
catch (Exception e)
{
Console.WriteLine("Exception: " + e);
}
}
private static void _TestSOCode()
{
using (var tcp = new TcpClient())
{
var c = tcp.BeginConnect(IPAddress.Parse("8.8.8.8"), 8080, null, null);
var success = c.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(1));
if (!success)
{
Console.WriteLine("Before cleanup");
tcp.Close();
tcp.EndConnect(c);
Console.WriteLine("After cleanup");
throw new Exception("Failed to connect.");
}
}
}
private static void _TestWithTcpClient()
{
TcpClient client = new TcpClient();
object o = new object();
Console.WriteLine("connecting TcpClient...");
client.BeginConnect("8.8.8.8", 8080, asyncResult =>
{
Console.WriteLine("connect completed");
try
{
client.EndConnect(asyncResult);
Console.WriteLine("client connected");
}
catch (NullReferenceException)
{
Console.WriteLine("client closed before connected: NullReferenceException");
}
catch (ObjectDisposedException)
{
Console.WriteLine("client closed before connected: ObjectDisposedException");
}
lock (o) Monitor.Pulse(o);
}, null);
Thread.Sleep(1000);
Stopwatch sw = Stopwatch.StartNew();
client.Close();
lock (o) Monitor.Wait(o);
Console.WriteLine("close took {0:0.00} seconds", sw.Elapsed.TotalSeconds);
Console.WriteLine();
}
private static void _TestWithSocket()
{
Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
object o = new object();
Console.WriteLine("connecting Socket...");
socket.BeginConnect("8.8.8.8", 8080, asyncResult =>
{
Console.WriteLine("connect completed");
try
{
socket.EndConnect(asyncResult);
Console.WriteLine("socket connected");
}
catch (ObjectDisposedException)
{
Console.WriteLine("socket closed before connected");
}
lock (o) Monitor.Pulse(o);
}, null);
Thread.Sleep(1000);
Stopwatch sw = Stopwatch.StartNew();
socket.Close();
lock (o) Monitor.Wait(o);
Console.WriteLine("close took {0:0.00} seconds", sw.Elapsed.TotalSeconds);
Console.WriteLine();
}
}
不幸的是,您没有提供演示该问题的实际完整代码示例。如果在您的环境中,上面的代码演示了您所描述的问题,因为它在我的环境中没有这样做,那么这显然意味着您的环境中存在某些问题导致了问题。不同的操作系统版本、不同的.NET版本等。
在这种情况下,您应该具体说明您的环境中可能相关的特定方面。
如果上面的代码示例按预期工作,并且没有演示您所描述的问题,那么您只需找出您的代码中有什么不同并导致问题。在这种情况下,如果您仍然无法真正找出问题所在,您应该发布a minimal, complete代码示例 https://stackoverflow.com/help/mcve这说明了问题所在。