为什么选择Thread.Sleep(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);
}
}
从NUnit测试中调用方法:
[Test]
public void AsyncTcpClientNoExceptionTest()
{
var asyncAwait = new AsyncTcpClientDemos();
// TODO: find out why this is not throwing exception
asyncAwait.ConnectTcpClientNoException();
}
答案 0 :(得分:6)
async
方法永远不会直接抛出异常。相反,如果在方法体内引发异常,则异步方法返回的任务将出现故障。
睡眠未执行,因为异常阻止方法的其余部分执行 - 只是异常通过Task
传播而不是直接堆叠。
如果您真的希望方法的第一部分抛出异常,可以将其拆分为两个。例如:
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
}
答案 1 :(得分:3)
为什么这段代码不会抛出System.Net.Sockets.SocketException 如果没有指定await?
正是因为如此。你还没有等待返回的任务。如果您愿意等待,您会看到异常传播:
[Test]
public async Task AsyncTcpClientNoExceptionTest()
{
var asyncAwait = new AsyncTcpClientDemos();
await asyncAwait.ConnectTcpClientNoException();
}
即使通过同步阻止你也可以看到(正如@Luann所建议的那样)(只是为了明确说明,不要实际使用它):
[Test]
public void AsyncTcpClientNoExceptionTest()
{
var asyncAwait = new AsyncTcpClientDemos();
asyncAwait.ConnectTcpClientNoException().GetAwaiter().GetResult();
}
当您使用async void
时,您就会强行解雇并忘记&#34;执行方式,您完全放弃故障任务。这恰好产生了吞咽异常的不良行为。如果您注册TaskScheduler.UnobservedTaskException
,您将能够看到当任务完成时,此事件将会触发。
为什么选择Thread.Sleep(4000);没有执行?
正如John所说,因为实际上发生了,但它并没有反映在您编写的代码中。将执行更改为正确等待任务将向您显示。