[Microsoft bot builder sdk] 如何在Microsoft bot应用程序中创建子线程或工作线程,该应用程序可以连续收听第三方Web APi并在不同连接器上发布给用户。
我创建了一个机器人,并希望该机器人不断收听第三方Web API。这项工作应该在一个单独的线程中完成。但是如果我在Dialog类中创建一个线程,它就不会向用户发布响应,因为在等待用户输入时对话框对象会被挂起。
[Serializable]
public class SampleDialog : IDialog<object>
{
protected int count = 1;
[NonSerialized]
Thread ChildTask;
public async Task StartAsync(IDialogContext context)
{
ChildTask = new Thread(new ParameterizedThreadStart(RunChildTask));
ChildTask.Start(context);
context.Wait(MessageReceivedAsync);
}
private void RunChildTask(object context)
{
IDialogContext contex = context as IDialogContext;
while (true)
{
this.count++;
contex.PostAsync($"{this.count++}: You said From child");
Thread.Sleep(1000);
}
}
public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
var message = await argument;
if (message.Text == "reset")
{
PromptDialog.Confirm(
context,
AfterResetAsync,
"Are you sure you want to reset the count?",
"Didn't get that!",
promptStyle: PromptStyle.None);
}
else
{
await context.PostAsync($"{this.count++}: You said {message.Text}");
context.Wait(MessageReceivedAsync);
}
}
调用RunChildTask方法但不回发给用户。
答案 0 :(得分:0)
它无法工作的原因是因为实现了聊天机器人的技术的性质。聊天机器人使用ASP.NET Web API,它像所有其他Web应用程序(例如WebForms或MVC)一样是无状态的。这意味着请求从客户端(在本例中为Bot Connector)到达,请求由聊天机器人处理,聊天机器人响应,聊天机器人的类实例有资格进行垃圾回收。当下一个请求进入时,它会为您的聊天机器人创建另一个Web API实例。
由于类实例不再具有引用,因此服务也不会。您刚刚启动的线程不再具有对服务的有效引用。因此,您有一个竞争条件,聊天机器人的正常处理在您启动的线程成功执行之前完成。因为它是一种竞争条件,所以有时候线程会幸运并发布一条消息,当它有时只能工作时可能会令人困惑。对于此类任务,您应该考虑更持久的实现,例如VM上的云服务或Windows服务。