RavenDb LoadAsync 不返回也不抛出异常

RavenDb LoadAsync Not Returning and Not Throwing Exceptions

我正在尝试通过 WebAPI 调用从 RavenDb 加载文档。当我打开一个异步 IDocumentSession 并调用 LoadAsync 时,我没有得到任何异常或结果,线程立即退出,没有错误代码。

我能够绕过 API 的所有结构并重现错误。

这是无效的代码:

    public IHttpActionResult GetMyObject(long id)
    {
        try
        {
            var session = RavenDbStoreHolderSingleton.Store.OpenAsyncSession();
            var myObject= session.LoadAsync<MyObject>("MyObject/1").Result;

            return Ok(myObject);

        }
        catch (Exception e)
        {
            return InternalServerError(e);
        }
    }

我只是简单地将对象的Id硬编码为1进行测试,但是为不存在的对象(例如"MyObject/1")调用该函数具有相同的结果。

但是,这段代码有效:

    public async Task<IHttpActionResult> GetMyObject(long id)
    {
        try
        {
            var session = RavenDbStoreHolderSingleton.Store.OpenAsyncSession();
            var myObject= await session.LoadAsync<MyObject>("MyObject/1");

            return Ok(myObject);

        }
        catch (Exception e)
        {
            return InternalServerError(e);
        }
    }

我 tried/fiddled 的事情:

所以我想我偶然发现了一个 "fix",但是 有人可以解释为什么其中一个会以如此奇怪的方式失败而另一个却可以正常工作吗?

在实际应用中,API调用没有async/await对,但是 拨打电话实际上是在使用 async/await。

这是失败的存储库 class,这导致我调查了这个问题:

    public async Task<MyObject> Load(string id) 
    { 
        return await _session.LoadAsync<MyObject>(id); 
    } 

失败的第一部分是按照设计,对于 ASP.Net 异步调用,当您在任务 returned 和相同的同步上下文中调用结果时,您正在阻塞同步上下文需要调用 return 数据。查看以下 link 作者 Stephen Cleary,其中详细解释了相同的机制。

第二部分有效,因为这是正确的使用方式,并且不会再陷入僵局。第一部分只有在您使用控制台应用程序时才能工作,它没有要阻止的同步上下文,即使其他 UI 像 winforms 也会有类似的问题,需要使用代码的第二部分