繁体   English   中英

如何从异步方法向调用者抛出异常?

[英]How to throw exception to caller from async method?

今天我读了很多关于async / await的内容,这让我大吃一惊。 我无法理解为什么以下测试通过。

[Test]
public void Test()
{
    var listener = new AsyncHttpListener();
    listener.ListeningAsync();

    try
    {
        new WebClient().DownloadString("http://localhost:8080/");
    }
    catch (Exception)
    {
    }

    listener.Close();
}

public class AsyncHttpListener
{
    private readonly HttpListener listener;

    public AsyncHttpListener()
    {
        listener = new HttpListener();
        listener.Prefixes.Add("http://localhost:8080/");
        listener.Start();
    }

    public void Close()
    {
        listener.Close();
    }

    public async void ListeningAsync()
    {
        var context = await listener.GetContextAsync();
        HandleContext(context);
    }

    private void HandleContext(HttpListenerContext context)
    {
        throw new Exception("test excpetion");
    }
}


测试通过,但输出包含:

System.Exception
test excpetion
   at AsyncHttpListenerTest.AsyncHttpListener.HandleContext(HttpListenerContext context) in AsyncHttpListener.cs: line 30
   at AsyncHttpListenerTest.AsyncHttpListener.d__0.MoveNext() in AsyncHttpListener.cs: line 25
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.b__1(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()

我希望异常将从任务线程(HandleContext()方法)传输到调用者上下文并且测试失败。 我怎么能得到这种行为?

使您的方法async Task而不是async void ,并使您的测试方法async Task而不是void

public async Task ListeningAsync()
{
    var context = await listener.GetContextAsync();
    HandleContext(context);
}

[Test]
public async Task Test()
{
    var listener = new AsyncHttpListener();
    await listener.ListeningAsync();

    try
    {
        new WebClient().DownloadString("http://localhost:8080/");
    }
    catch (Exception)
    {
    }

    listener.Close();
}

有几个很好的理由可以避免async void 错误处理就是其中之一。 async void方法引发的错误直接转到方法启动时当前的SynchronizationContext

测试通过的原因是async方法可能在完成之前返回给调用者。 测试运行器看到测试方法返回(没有抛出异常),并将其标记为“已通过”。 如果从测试方法返回Task ,则测试运行器知道在考虑测试完成之前等待Task完成。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM