在Web上下文(IIS)中运行时,我没有从异步DocumentDB ReplaceDocument方法获得响应。在本地运行时,它工作得很好。根据我的研究,这似乎与UI线程的冲突死锁有关吗?
我从其他异步调用中得到了很好的响应:
this.Client.ReadDatabaseAsync(UriFactory.CreateDatabaseUri(this.DatabaseName)).Result;
// and
this.Client.CreateDatabaseAsync(new Database { Id = this.DatabaseName }).Result;
// etc
我没有在IIS上下文中使用await似乎永远不会响应。我不知道为什么,所以我删除了所有的异步等待,并开始使用.Result
,现在一切正常,除了以下方法。
根据这个问题Call to await GetFileAsync() never returns and app hangs in WinRT app。我已设置ConfigureAwait(false)
,正在呼叫GetResult()
。但是该方法不会返回,并且线程最终会在不返回的情况下关闭。
var task = this.Client.ReplaceDocumentAsync(this.GetDocumentLink(d.id), d, options);
var configuredTask = task.ConfigureAwait(false);
var awaiter = configuredTask.GetAwaiter();
var result = awaiter.GetResult();
我也尝试过以下排列:
// in a spereate async method
await this.Client.ReplaceDocumentAsync(this.GetDocumentLink(d.id), d, options);
await this.Client.ReplaceDocumentAsync(this.GetDocumentLink(d.id), d, options).ConfigureAwait(false);
// as well as trying a call back
.GetAwaiter().OnCompleted(() => /* never gets here either */);
修改
我在Web.config
(来自:What's the meaning of "UseTaskFriendlySynchronizationContext"?)
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
and
<system.web>
<compilation debug="true" targetFramework="4.6.1" />
<httpRuntime targetFramework="4.5" />
</system.web>
答案 0 :(得分:4)
我相信你会看到我在博客上描述的common deadlock issue。
最好的解决方案不试图通过在任何地方使用ConfigureAwait(false)
来避免它,因为必须使用无处不在。因此,如果您忘记了一个地方,或者某些库代码没有使用它(这很常见),那么就无法避免死锁。
最好的解决方案是使用await
。将Task.Wait()
,Task<T>.Result
和Task.GetAwaiter().GetResult()
的所有来电替换为await
:
await this.Client.ReadDatabaseAsync(UriFactory.CreateDatabaseUri(this.DatabaseName));
await this.Client.CreateDatabaseAsync(new Database { Id = this.DatabaseName });
var result = await this.Client.ReplaceDocumentAsync(this.GetDocumentLink(d.id), d, options);
我没有使用await,因为在IIS上下文似乎永远不会响应。
请确保您的目标是.NET 4.5 并且已在targetFramework
中将web.config
设置为4.5。
答案 1 :(得分:0)
在我的情况下,有类似的任务取消/错误,显示内部异常&#34; DictionaryError&#34;或聚合异常。至少我发现造成问题的主要原因只是使用端点到cosmosDb模拟器和http://。更改后https://localhost:8081 - 一切都开始工作了。