C# 为什么TcpClient.Connect即使异步方法正在同步运行,也不会在异步方法中引发异常 为什么即使未指定等待,此代码也不会引发System.Net.Sockets.SocketException?(没有服务器在指定端口侦听)
为什么线程。睡眠(4000);没有被执行吗C# 为什么TcpClient.Connect即使异步方法正在同步运行,也不会在异步方法中引发异常 为什么即使未指定等待,此代码也不会引发System.Net.Sockets.SocketException?(没有服务器在指定端口侦听),c#,.net,multithreading,asynchronous,async-await,C#,.net,Multithreading,Asynchronous,Async Await,为什么线程。睡眠(4000);没有被执行吗 public class AsyncTcpClientDemos { private static readonly ILog Logger = LogProvider.GetCurrentClassLogger(); public async Task ConnectTcpClientNoException() { Logger.Debug("ConnectTcpClientNoException() - start
public class AsyncTcpClientDemos
{
private static readonly ILog Logger = LogProvider.GetCurrentClassLogger();
public async Task ConnectTcpClientNoException()
{
Logger.Debug("ConnectTcpClientNoException() - start");
var tcp = new TcpClient();
tcp.Connect("127.0.0.1", 9045);
Thread.Sleep(4000);
}
}
从NUnit测试中调用方法:
[Test]
public void AsyncTcpClientNoExceptionTest()
{
var asyncAwait = new AsyncTcpClientDemos();
// TODO: find out why this is not throwing exception
asyncAwait.ConnectTcpClientNoException();
}
async
方法从不直接抛出异常。相反,如果在方法体中引发异常,则异步方法返回的任务将出现故障
之所以不执行睡眠,是因为异常确实阻止了方法的其余部分执行——只是异常通过任务
传播,而不是直接在堆栈上传播
如果确实希望方法的第一部分抛出异常,可以将其拆分为两部分。例如:
public Task FooAsync(int x, int y)
{
if (x < y)
{
// This will be thrown straight to the caller, in the
// normal way
throw new ArgumentException("...");
}
return FooAsyncImpl(x, y);
}
private async Task FooAsyncImpl(int x, int y)
{
// Any exceptions thrown here will be propagated via the task
}
publictasync(intx,inty)
{
if(x异步方法从不直接引发异常。相反,如果在方法体中引发异常,则异步方法返回的任务将出现故障
之所以不执行睡眠,是因为异常确实阻止了方法的其余部分执行——只是异常通过任务
传播,而不是直接在堆栈上传播
如果确实希望方法的第一部分抛出异常,可以将其拆分为两部分。例如:
public Task FooAsync(int x, int y)
{
if (x < y)
{
// This will be thrown straight to the caller, in the
// normal way
throw new ArgumentException("...");
}
return FooAsyncImpl(x, y);
}
private async Task FooAsyncImpl(int x, int y)
{
// Any exceptions thrown here will be propagated via the task
}
publictasync(intx,inty)
{
if(x
为什么此代码甚至没有抛出System.Net.Sockets.SocketException
如果没有指定等待
正因为如此。您没有等待返回的任务。如果您愿意等待,您将看到异常传播:
[Test]
public async Task AsyncTcpClientNoExceptionTest()
{
var asyncAwait = new AsyncTcpClientDemos();
await asyncAwait.ConnectTcpClientNoException();
}
即使通过同步阻塞,您也可以看到(正如@luan所建议的那样)(只是为了说明这一点,实际上不要使用它):
当您使用async void
时,您将强制执行一种“触发并忘记”的执行方式,在这种方式下,您将完全放弃出现故障的任务。这恰恰产生了吞咽异常的不希望的行为。如果您注册,您将能够看到,当任务完成时,将触发此事件
为什么线程。睡眠(4000);没有被执行吗
public class AsyncTcpClientDemos
{
private static readonly ILog Logger = LogProvider.GetCurrentClassLogger();
public async Task ConnectTcpClientNoException()
{
Logger.Debug("ConnectTcpClientNoException() - start");
var tcp = new TcpClient();
tcp.Connect("127.0.0.1", 9045);
Thread.Sleep(4000);
}
}
正如John所说,因为异常确实发生了,所以它不会反映在您编写的代码中。将执行更改为正确等待任务将显示这一点
为什么此代码甚至没有抛出System.Net.Sockets.SocketException
如果没有指定等待
正因为如此。您没有等待返回的任务。如果您愿意等待,您将看到异常传播:
[Test]
public async Task AsyncTcpClientNoExceptionTest()
{
var asyncAwait = new AsyncTcpClientDemos();
await asyncAwait.ConnectTcpClientNoException();
}
即使通过同步阻塞,您也可以看到(正如@luan所建议的那样)(只是为了说明这一点,实际上不要使用它):
当您使用async void
时,您将强制执行一种“触发并忘记”的执行方式,在这种方式下,您将完全放弃出现故障的任务。这恰恰产生了吞咽异常的不希望的行为。如果您注册,您将能够看到,当任务完成时,将触发此事件
为什么线程。睡眠(4000);没有被执行吗
public class AsyncTcpClientDemos
{
private static readonly ILog Logger = LogProvider.GetCurrentClassLogger();
public async Task ConnectTcpClientNoException()
{
Logger.Debug("ConnectTcpClientNoException() - start");
var tcp = new TcpClient();
tcp.Connect("127.0.0.1", 9045);
Thread.Sleep(4000);
}
}
正如John所说,因为异常确实发生了,所以它不会反映在您编写的代码中。将任务的执行更改为正确等待将显示这一点。您不能忽略wait
。尝试执行类似于AsyncWait.ConnectTcpClientNoException().GetWaiter().GetResult()
的操作-这将导致在测试方法中引发异常。否则它就被丢弃了(更确切地说,留在返回的任务中,但忽略返回值时这对您没有任何帮助)。或者只是AsyncWait.ConnectTcpClientNoException().Wait()您不能忽略Wait
。尝试执行类似于AsyncWait.ConnectTcpClientNoException().GetWaiter().GetResult()
的操作-这将导致在测试方法中引发异常。否则它就被丢弃了(更确切地说,留在返回的任务中,但忽略返回值时这对您没有任何帮助),或者只是AsyncWait.ConnectTcpClientNoException().Wait(),我使用了async task
。但是异步无效
也有同样的行为。@Andriy F是否会传播异常?不,在这两种情况下都不会。是否打开了第一次机会异常?我没有在调试模式下运行此[测试]。我使用了异步任务
。但是async void
也有同样的行为。@Andriy F是否会传播异常?不,在这两种情况下都不会。是否打开了第一次机会异常?我不会在调试模式下运行此[测试]