我尝试使用.NET Core并希望连接到本地TCP服务器。我同步执行时没有问题(请参阅第一个Connect
方法)。当我尝试使用async
/ await
(请参阅第二个ConnectAsync
方法)时,它会变得疯狂并几乎无法辨认。如果我正确使用TcpClient,我不会起诉,因为网上还没有那么多的例子。调用TcpClient.GetStream
后,确切的问题就开始了。我试图通过Visual Studio Code中的JustMyCode
禁用和All exceptions
复选框调试此功能 - 但它不会跳转到TcpClient.GetStream
。
async
模式下的观察:
TcpClient.GetStream
崩溃Console.WriteLine
)The program 'bla' has exited with code 0 (0x00000000)
)我的系统/项目设置:
代码:
public class Connection
{
private TcpClient _client;
public NetworkStream Stream { get; private set; }
private CancellationTokenSource _token;
public Connection()
{
_token = new CancellationTokenSource();
_client = new TcpClient();
}
public void Connect(string host, int port)
{
Console.WriteLine("connecting...");
_client.ConnectAsync(host, port);
Console.WriteLine("connected!");
while (!_client.Connected)
{
Thread.Sleep(20);
}
Console.WriteLine("getting stream...");
Stream = _client.GetStream(); // works because of Thread.Sleep above until the socket is connected
Console.WriteLine("got stream!");
}
public async Task ConnectAsync(string host, int port)
{
Console.WriteLine("connecting...");
await _client.ConnectAsync(host, port);
Console.WriteLine("connected!");
// I know I could check for TcpClient.Connected but I see in debugger that the property is True
Console.WriteLine("getting stream...");
Stream = _client.GetStream(); // crash in GetStream / crash after this function has returned
Console.WriteLine("got stream!"); // sometimes this is going to be printed, sometimes not
}
// ...
}
答案 0 :(得分:5)
您所描述的问题指向应用程序死亡的主线程。要正确识别该问题,必须查看整个应用程序以及在任何给定时刻处于活动状态的线程。
但是,例如,一个简单的控制台应用程序会在主要子终止后立即终止。根据您调用ConnectAsync
函数的方式,您可能缺少确保主循环不会终止的内容。确保您的主要入口点不是async
函数,因为它会在它到达第一个await
后立即终止。
两种方法之间发生的主要区别是ConnectAsync
方法实际上很可能切换线程,并在另一个线程中执行第二部分,而不是像{{1}那样阻塞它所调用的线程功能确实。
它准确地解释了您所描述的行为。
之后的一段时间Connect
执行行后,应用程序的主循环终止并导致整个.NET VM关闭。