【问题标题】:Why DocumentDbBotDataStore does not cause a deadlock? [duplicate]为什么 DocumentDbBotDataStore 不会导致死锁? [复制]
【发布时间】:2018-06-10 05:34:37
【问题描述】:

announcement 之后,即开箱即用的机器人状态管理将被弃用,Microsoft 提供了 the documentation 解释如何设置自定义 BotState 数据提供程序。

这就是我根据文档插入自定义 BotState 提供程序的方式:

protected void Application_Start()
{
    var uri = new Uri(ConfigurationManager.AppSettings["DocumentDbUrl"]);
    var key = ConfigurationManager.AppSettings["DocumentDbKey"];
    var store = new DocumentDbBotDataStore(uri, key);

    Conversation.UpdateContainer(builder =>
    {
        builder.Register(c => store)
            .Keyed<IBotDataStore<BotData>>(AzureModule.Key_DataStore)
            .AsSelf()
            .SingleInstance();

        builder.Register(c => new CachingBotDataStore(store, CachingBotDataStoreConsistencyPolicy.ETagBasedConsistency))
            .As<IBotDataStore<BotData>>()
            .AsSelf()
            .InstancePerLifetimeScope();

    });
}

现在,如果我们看一下DocumentDbBotDataStore 构造函数,它是可用的on GitHub

public DocumentDbBotDataStore(Uri serviceEndpoint, string authKey, string databaseId = "botdb", string collectionId = "botcollection")
    : this(new DocumentClient(serviceEndpoint, authKey), databaseId, collectionId) { }

public DocumentDbBotDataStore(IDocumentClient documentClient, string databaseId = "botdb", string collectionId = "botcollection")
{
    SetField.NotNull(out this.databaseId, nameof(databaseId), databaseId);
    SetField.NotNull(out this.collectionId, nameof(collectionId), collectionId);

    this.documentClient = documentClient;
    this.databaseId = databaseId;
    this.collectionId = collectionId;

    CreateDatabaseIfNotExistsAsync().GetAwaiter().GetResult();
    CreateCollectionIfNotExistsAsync().GetAwaiter().GetResult();
}

您可以看到异步方法 CreateDatabaseIfNotExistsAsyncCreateDatabaseIfNotExistsAsync 使用 GetAwaiter() .GetResult() 调用同步调用,这可能会导致死锁。 Here is这两个方法的实现是怎样的:

private async Task CreateDatabaseIfNotExistsAsync()
{
    try
    {
        await documentClient.ReadDatabaseAsync(UriFactory.CreateDatabaseUri(databaseId));
    }
    catch (DocumentClientException e)
    {
        if (e.StatusCode == HttpStatusCode.NotFound)
        {
            await documentClient.CreateDatabaseAsync(new Database { Id = databaseId });
        }
        else
        {
            throw;
        }
    }
}

如您所见,甚至没有调用 ConfigureAwait(false) 来降低死锁的风险。

问题:

这个设置怎么可能从来没有导致死锁?

【问题讨论】:

  • 我会说没有 SynchronizationContext

标签: c# .net async-await botframework


【解决方案1】:

Application_Start 保证在应用程序域的生命周期内只被调用一次:https://msdn.microsoft.com/en-us/library/ms178473.aspx#Anchor_1

Application_Start中创建数据库和集合是安全的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-09
    • 2019-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-20
    • 1970-01-01
    相关资源
    最近更新 更多