在停止服务器并尝试再次启动它之后,我陷入了TcpListener
类的问题。我基本上想做的是使用AcceptTcpClientAsync()
方法来处理传入的连接请求,并提供重新启动服务器的可能性。
最小示例:
class Program
{
private static TcpListener listener;
static void Main(string[] args)
{
StartServerAsync();
StopServer();
StartServerAsync();
Console.ReadKey();
}
private static void StopServer()
{
if (listener != null)
listener.Stop();
}
private async static void StartServerAsync()
{
listener = new TcpListener(IPAddress.Loopback, 1234);
listener.Start();
while (true)
{
var client = await listener.AcceptTcpClientAsync();
}
}
}
第二次致电await listener.AcceptTcpClientAsync()
时,我收到一个ObjectDisposedException
的套接字。
任何想法或意见如何克服这个问题?
谢谢!
答案 0 :(得分:2)
似乎是静态变量和async void
的不健康组合。在进行一些重写以删除静态变量并使用返回侦听器的工厂方法后,仍然会发生异常。但是现在我在调用Stop()
的相应实例的await调用中得到了它。这是有道理的,因为接受调用必须在停止后返回,但是它必须表示没有客户端可用(通过抛出异常来实现)。
所以avoid async void
,尤其是与静态成员结合使用时。似乎确实有毒,对不起我没有更深入的解释(链接除外)。
private static void Main(string[] args)
{
var listener1 = StartServerAsync(1234).Result;
StopServer(listener1);
var listener2 = StartServerAsync(1235).Result;
StopServer(listener2);
var listener3 = StartServerAsync(1236).Result;
StopServer(listener3);
Console.ReadKey();
}
private static void StopServer(TcpListener listener)
{
if (listener != null)
{
Console.WriteLine("Stop on port "+ listener.LocalEndpoint);
listener.Stop();
listener = null;
}
}
private static async Task<TcpListener> StartServerAsync(int port)
{
var listener = new TcpListener(IPAddress.Loopback, port);
listener.Start();
Console.WriteLine("Started on port " + port);
var task = Task.Run(async () => await WaitForConnection(listener));
await Task.Delay(100);
return listener;
}
private static async Task WaitForConnection(TcpListener listener)
{
while (true)
{
try
{
var client = await listener.AcceptTcpClientAsync();
}
catch (ObjectDisposedException)
{
Console.WriteLine("Failed on " + listener.LocalEndpoint);
}
}
}