.NET Core:TcpClient.GetStream 使用异步时崩溃
.NET Core: TcpClient.GetStream crashes when using async
我尝试使用 .NET Core 并想连接到本地 TCP 服务器。当我同步执行时没有问题(请参阅第一个 Connect
方法)。当我尝试使用 async
/await
(参见第二个 ConnectAsync
方法)时,它变得疯狂并且几乎无法调试。如果我正确使用 TcpClient,我不会起诉,因为网络上还没有那么多示例。确切的问题在调用 TcpClient.GetStream
之后开始。我尝试在 Visual Studio 代码中禁用 JustMyCode
和 All exceptions
复选框进行调试 - 但它不会跳入 TcpClient.GetStream
.
async
模式下的观察:
- 有时直接在
TcpClient.GetStream
中崩溃
- 有时它会在调用函数 returns 后崩溃(我看到最后一个
Console.WriteLine
有时会出现在控制台中)
- 程序立即停止,调试器关闭(没有抛出异常)
- return 代码始终为零 (
The program 'bla' has exited with code 0 (0x00000000)
)
我的 system/project 设置:
- Windows 10 64 位(教育)
- .NET 核心 1.0.0
- 控制台应用程序
- 本地 TCP 服务器,因此没有连接问题
- Visual Studio 代码(应该无关紧要)
代码:
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
}
// ...
}
您所描述的问题表明您的应用程序的主线程正在死机。要正确识别该问题,必须查看整个应用程序和在任何给定时刻处于活动状态的线程。
但是,例如,一个简单的控制台应用程序会在主子程序终止后立即终止。根据您调用 ConnectAsync
函数的方式,您可能缺少确保主循环不终止的东西。确保您的主入口点不是 async
函数,因为它会在到达第一个 await
.
时立即终止
这两种方法之间的主要区别在于 ConnectAsync
方法实际上很可能会切换线程并在不同的线程中执行第二部分,而不是像 [= 那样阻塞调用它的线程15=] 功能确实如此。
它准确地解释了您所描述的行为。
之后的一段时间
await _client.ConnectAsync(host, port);
行执行应用程序的主循环终止并导致整个 .NET VM 关闭。
我尝试使用 .NET Core 并想连接到本地 TCP 服务器。当我同步执行时没有问题(请参阅第一个 Connect
方法)。当我尝试使用 async
/await
(参见第二个 ConnectAsync
方法)时,它变得疯狂并且几乎无法调试。如果我正确使用 TcpClient,我不会起诉,因为网络上还没有那么多示例。确切的问题在调用 TcpClient.GetStream
之后开始。我尝试在 Visual Studio 代码中禁用 JustMyCode
和 All exceptions
复选框进行调试 - 但它不会跳入 TcpClient.GetStream
.
async
模式下的观察:
- 有时直接在
TcpClient.GetStream
中崩溃 - 有时它会在调用函数 returns 后崩溃(我看到最后一个
Console.WriteLine
有时会出现在控制台中) - 程序立即停止,调试器关闭(没有抛出异常)
- return 代码始终为零 (
The program 'bla' has exited with code 0 (0x00000000)
)
我的 system/project 设置:
- Windows 10 64 位(教育)
- .NET 核心 1.0.0
- 控制台应用程序
- 本地 TCP 服务器,因此没有连接问题
- Visual Studio 代码(应该无关紧要)
代码:
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
}
// ...
}
您所描述的问题表明您的应用程序的主线程正在死机。要正确识别该问题,必须查看整个应用程序和在任何给定时刻处于活动状态的线程。
但是,例如,一个简单的控制台应用程序会在主子程序终止后立即终止。根据您调用 ConnectAsync
函数的方式,您可能缺少确保主循环不终止的东西。确保您的主入口点不是 async
函数,因为它会在到达第一个 await
.
这两种方法之间的主要区别在于 ConnectAsync
方法实际上很可能会切换线程并在不同的线程中执行第二部分,而不是像 [= 那样阻塞调用它的线程15=] 功能确实如此。
它准确地解释了您所描述的行为。
之后的一段时间await _client.ConnectAsync(host, port);
行执行应用程序的主循环终止并导致整个 .NET VM 关闭。