给代码有限的时间来执行

时间:2017-03-01 18:15:16

标签: c# multithreading task

我在应用中有一行代码如下:

string botMessage = chatterBotSession.Think(input);

它正在查询聊天机器人服务并将响应存储在botMessage中。然而,有时,聊天机器人可能需要很长时间才能想到响应。

有没有一种方法可以像平常一样运行代码,但是如果它在一秒内没有完成取消它然后运行一些处理程序可以提醒用户服务花了太长时间?

喜欢,通常我可以这样做:

string botMessage = chatterBotSession.Think(input);
Console.WriteLine("The bot responded with: " + botMessage);

但是如果机器人很慢,第二行就不会被执行(足够快)。我怎样才能将机器人的“思考”时间限制为一秒钟,并且如果成功完成则运行其余代码(通常会运行),或者运行单独的代码以显示错误消息尚未完成。

3 个答案:

答案 0 :(得分:2)

您可以在Task.Run调用中包装bot的服务调用,并等待预定义的时间。它看起来像这样

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();
}

答案 1 :(得分:0)

使用带有超时的CancellationTokenSource来限制任务执行非常容易:

var cancellationToken = new CancellationTokenSource();
var task = chatterBotSession.Think(cancellationToken.Token);
cancellationToken.CancelAfter(TimeSpan.FromMilliseconds(1000)); // cancel after 1sec
await task;

Think方法中,您应该添加对CancellationToken.ThrowIfCancellationRequested

的调用

答案 2 :(得分:0)

致电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;
    }

}