RavenDb LoadAsync未返回且未引发异常



我正试图通过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);
        }
    }

我尝试/摆弄过的东西:

  • 更改调试中捕获的异常
  • 仔细监控Raven Studio,看看我是否能发现任何问题(我没有,但我不确定我找对了地方)
  • 在没有附加调试器的情况下运行API,以查看是否发生了错误或Raven Studio中是否出现了某些内容(无更改)

所以我想我偶然发现了一个"修复",但有人能解释为什么其中一个会以如此奇怪的方式失败,而另一个会非常好地工作吗

在实际应用程序中,API调用没有async/await对,但进行调用的代码实际上使用async/await。

这是导致我研究这个问题的失败的存储库类:

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

失败的第一部分是根据设计,对于ASP.Net异步调用,当您对返回的任务调用Result时,您正在阻塞同步上下文,并且调用需要相同的同步上下文才能返回数据。查看Stephen Cleary的以下链接,其中详细解释了相同的机制。

第二部分之所以有效,是因为这是正确的使用方式,而且它不再陷入死锁。第一部分只能在您使用Console应用程序的情况下工作,该应用程序没有要阻止的同步上下文,即使是像winforms这样的其他UI也会有类似的问题,需要使用代码的第二部分

最新更新