我在一个看起来像这样的应用中有一系列代码行:
string botMessage = chatterBotSession.Think(input);
它正在查询聊天机器人服务,并将响应存储在botMessage
中。但是,有时候,聊天机器人可能需要太长时间才能想到回应。
有没有一种方法可以像正常情况一样运行代码,但是如果它在一秒钟内未完成,然后运行一些处理程序,可以提醒用户服务时间太长?
喜欢,通常我可能会这样做:
string botMessage = chatterBotSession.Think(input);
Console.WriteLine("The bot responded with: " + botMessage);
但是,如果机器人速度慢,则第二行不会执行(足够快)。我如何将机器人的"思考"时间限制为一秒钟,并在完成后立即运行其余的代码(通常会运行),如果它成功或运行单独的代码,以显示错误消息(如果它)显示出错误消息。尚未完成。
您可以将机器人的服务调用包装在任务中。运行调用并等待预定的时间。看起来像这样
static void Main(string[] args)
{
var task = Task.Run(() => chatterBotSession.Think(input));
if (task.Wait(1000))
{
Console.WriteLine(task.Result);
}
else
{
Console.WriteLine("Couldn't get an answer in a timely manner");
}
Console.ReadLine();
}
通过在超时使用CancellationTokenSource
时限制任务执行非常容易:
var cancellationToken = new CancellationTokenSource();
var task = chatterBotSession.Think(cancellationToken.Token);
cancellationToken.CancelAfter(TimeSpan.FromMilliseconds(1000)); // cancel after 1sec
await task;
在Think
方法中,您应该将呼叫添加到CancellationToken.ThrowIfCancellationRequested
调用bot:
static void Main(string[] args)
{
TalkingBot bot = new TalkingBot();
try
{
Console.WriteLine("Thinking started...");
Console.WriteLine(bot.Think("Some input...", 2000));
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex.Message);
}
Console.ReadLine();
}
和bot本身:
class TalkingBot
{
string input = null;
int timeout = 0;
string asyncThnikResult = null;
public string Think(string input, int timeout)
{
DateTime timeLimit = DateTime.Now.AddMilliseconds(timeout);
this.input = input;
this.timeout = timeout;
System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(AsyncThnik));
thread.Start();
//wait for result, in this case
while (string.IsNullOrEmpty(asyncThnikResult))
{
if (timeLimit <= DateTime.Now)
{
throw new Exception("Timeout occured!");
}
System.Threading.Thread.Sleep(10);
}
//return result...
return this.asyncThnikResult;
}
/// <summary>
/// Do your thing async...
/// </summary>
void AsyncThnik()
{
string temp = "This value will never be returned due to timeout limit...";
System.Threading.Thread.Sleep(timeout + 1000); //add second to produce timeout...
this.asyncThnikResult = temp;
}
}