超时后更新 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 必须响应团队,否则此问题会弹出最佳解决方案以实现主动消息概念
我要求发布到 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 必须响应团队,否则此问题会弹出最佳解决方案以实现主动消息概念