超时后更新 BotFramework 中的 activity

Updating an activity in BotFramework after a timeout

我要求发布到 MS Teams 的 Bot 消息应在超时期限后过期。为实现此目的,我在超时后在单独的线程上调用 UpdateAsyncActivity(),但这失败并出现 NullReferenceException:

System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.Bot.Builder.BotFrameworkAdapter.UpdateActivityAsync(ITurnContext turnContext, Activity activity, CancellationToken cancellationToken)
at Microsoft.Bot.Builder.TurnContext.<>c__DisplayClass31_0.<<UpdateActivityAsync>g__ActuallyUpdateStuff|0>d.MoveNext()--- End of stack trace from previous location where exception was thrown ---
at Microsoft.Bot.Builder.TurnContext.UpdateActivityInternalAsync(Activity activity, IEnumerable`1 updateHandlers, Func`1 callAtBottom, CancellationToken cancellationToken)
at Microsoft.Bot.Builder.TurnContext.UpdateActivityAsync(IActivity activity, CancellationToken cancellationToken)
at NotifyController.ClearCard(ITurnContext turnContext, Activity timeoutActivity, Int32 timeoutInMinutes) in NotifyController.cs:line 48

代码看起来像这样:

[Route("api/notify")]
[ApiController]
public class NotifyController : ControllerBase
{
    private IBotFrameworkHttpAdapter Adapter;
    private readonly string _appId;
    private readonly IConversationStorage _conversationStorage;

    public NotifyController(IBotFrameworkHttpAdapter adapter, IConfiguration configuration, IConversationStorage conversationStorage)
    {
        Adapter = adapter;
        _appId = configuration["MicrosoftAppId"] ?? string.Empty;
        _conversationStorage = conversationStorage;
    }

    [HttpPost]
    public async Task<IActionResult> PostForm([FromBody] RestData restData)
    {
        ConversationReference conversationReference =
            _conversationStorage.GetConversationFromStorage(restData.ConversationId);

        await ((BotAdapter)Adapter).ContinueConversationAsync(_appId, conversationReference, async (context, token) =>
            await BotCallback(restData.AdaptiveCard, context, token), default(CancellationToken));

        return new ContentResult();
    }

    private async Task BotCallback(string adaptiveCard, ITurnContext turnContext, CancellationToken cancellationToken)
    {
        var activity = MessageFactory.Attachment(adaptiveCard.ToAttachment());

        ResourceResponse response = await turnContext.SendActivityAsync(activity);

        var timeoutActivity = turnContext.Activity.CreateReply();
        timeoutActivity.Attachments.Add(AdaptiveCardExamples.TimeoutTryLater.ToAttachment());
        timeoutActivity.Id = response.Id;

        // SUCCESS
        //Thread.Sleep(10000);
        //await turnContext.UpdateActivityAsync(timeoutActivity);

        // FAIL
        Thread CardClearThread = new Thread(() => ClearCard(turnContext, timeoutActivity));
        CardClearThread.Start();
    }

    private async void ClearCard(ITurnContext turnContext, Activity timeoutActivity)
    {
        Thread.Sleep(10000);
        await turnContext.UpdateActivityAsync(timeoutActivity);
    }
}

我希望在单独的线程上发生超时,以便 PostForm() returns 在发送原始消息后立即响应。

我推测发生的事情是当主线程 returns 时正在处理 turnContext 的某些方面,导致睡眠线程在唤醒时失败。

有solution/alternative方法吗?

几分钟后,Bot 必须响应团队,否则此问题会弹出最佳解决方案以实现主动消息概念

https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-howto-proactive-message?view=azure-bot-service-4.0&tabs=csharp