繁体   English   中英

调试异步等待控制器操作

[英]Debugging async await controller action

我在ApiController中隐含了(我认为是)一个简单的异步方法,如下所示:

public class CommentsController : ApiController
{
    private static readonly IList<CommentModel> Comments;

    static CommentsController()
    {
        // Note: Removed to abbreviate - populate comments manually here.
    }

    [ResponseType(typeof (IList<CommentModel>))]
    [HttpGet]
    public async Task<IHttpActionResult> GetAllComments()
    {
        return await Task.Factory.StartNew(() =>
        {
            Thread.Sleep(10000); // Breakpoint #1
            return Ok(Comments); // Breakpoint #2
        });

        // Breakpoint #3
    }
}

注意我在上面放置的断点。

我期望发生的事情是在我单击“继续”时在#1处等待线程等待,但流程在此阶段继续通过#3。

然后,当睡眠结束后,再次继续并在#2处休息。

但是,在调试过程中,它似乎是同步的。

我的问题是,首先,这是真正的异步吗?如何调试它以进行验证,或者进行单元测试?

但是,在调试过程中,它似乎是同步的。

它是串行的(不是同步的),因为await关键字告诉该方法在该操作完成之前不要继续。 调试器将以串行方式逐步执行异步方法,这可以使它们显得同步。 这比让调试器跳到不相关的代码然后再跳回去要自然得多。

我的问题首先是这种真正的异步

它是假的异步的。 在实际代码中,您永远不会使用Task.Factory.StarNew

此外,对于ASP.NET应用程序,应避免将工作发送到线程池( StartNewTask.Run等)。 相反,您应该调用自然异步API。

如何调试它以进行验证,或者进行单元测试?

您可以调用该方法,确认任务尚未完成,然后等待它。 请注意,为避免出现竞争情况,您应该对控制器正在使用的任何异步服务进行存根。

断点3将永远不会被击中,应该不会。

Task.Factory.StartNew开头的Task将异步运行。
但是await基本上是等待Task完成执行,然后再继续当前方法,然后将执行返回给调用方。 因此,它为给定Task添加了延续
由于您要返回Task的结果,因此断点3将永远不会执行。

如果希望Breakpoint 3Task之后执行,则基本上有2个选项:

您可以添加延续:

    return await Task.Factory.StartNew(() =>
    {
        Thread.Sleep(10000); // Breakpoint #1
        return Ok(Comments); // Breakpoint #2
    }).ContinueWith((Task<IHttpActionResult> t) => 
    {
        //t.Result contains the result of the previous Task
        return t.Result; // Breakpoint #3
    });

或者(更简单),使用一个临时值并await

    var temp = await Task.Factory.StartNew(() =>
    {
        Thread.Sleep(10000); // Breakpoint #1
        return Ok(Comments); // Breakpoint #2
    });

    // Breakpoint #3
    return temp;

要在不等待执行完成的情况下调用async方法,只需忽略await 因此,如果您想并行执行5次GetAllComments ,可以这样做:

for(int i = 0; i < 5; i++)
    GetAllComments();

断点3怎么会被击中? 您在等待之前得到了回报。

因此,将发生的情况是,等待将生成状态机,并且在线程完成时将仅返回该值。

暂无
暂无

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

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