user3310334
user3310334

Reputation:

Give code limited amount of time to execute within

I have a line of code in an app that looks like this:

string botMessage = chatterBotSession.Think(input);

It's querying a chat bot service and stores the response in botMessage. Sometimes however, the chat bot can take too long to think of a response.

Is there a way I can run the code like normal, but if it doesn't complete in one second cancel it and then run some handler that can alert the user that the service took too long?

Like, normally I might do this:

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

but if the bot is slow the second line doesn't get executed (fast enough). How can I limit the bot's "thinking" time to one second, and run the rest of the code (that would normally run) as soon as it completes if it was successful or run a separate bit of code to display an error message if it hasn't completed.

Upvotes: 0

Views: 102

Answers (3)

Guillaume CR
Guillaume CR

Reputation: 3016

You can wrap the bot's service call in a Task.Run call and wait for it a predefined amount of time. It would look something like this

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

Upvotes: 2

Gregor Primar
Gregor Primar

Reputation: 6805

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

And Bot itself:

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

}

Upvotes: 0

Radin Gospodinov
Radin Gospodinov

Reputation: 2323

It is very easy to limit the task execution by using CancellationTokenSource with timeout:

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

In Think method you should add call to CancellationToken.ThrowIfCancellationRequested

Upvotes: 0

Related Questions