C# 为代码提供有限的执行时间

C# 为代码提供有限的执行时间,c#,multithreading,task,C#,Multithreading,Task,我在一个应用程序中有一行代码,如下所示: string botMessage = chatterBotSession.Think(input); 它正在查询聊天机器人服务,并将响应存储在botMessage中。但是,有时聊天机器人可能需要很长时间才能想到响应 是否有一种方法可以像正常情况一样运行代码,但如果代码不能在一秒钟内完成,请取消它,然后运行一些处理程序,提醒用户服务花费的时间太长 比如,通常我会这样做: string botMessage = chatterBotSession.Thi

我在一个应用程序中有一行代码,如下所示:

string botMessage = chatterBotSession.Think(input);
它正在查询聊天机器人服务,并将响应存储在
botMessage
中。但是,有时聊天机器人可能需要很长时间才能想到响应

是否有一种方法可以像正常情况一样运行代码,但如果代码不能在一秒钟内完成,请取消它,然后运行一些处理程序,提醒用户服务花费的时间太长

比如,通常我会这样做:

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

但是如果机器人速度慢,第二行就不能执行(足够快)。如何将机器人的“思考”时间限制在一秒钟内,并运行其余的代码(通常会运行)如果成功,则在任务完成后立即执行;如果未完成,则运行单独的代码位以显示错误消息。

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

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

Think
方法中,您应该添加对
CancellationToken的调用。通过使用
CancellationRequested
可以很容易地通过使用带超时的
CancellationTokenSource
来限制任务执行:

var cancellationToken = new CancellationTokenSource();
var task = chatterBotSession.Think(cancellationToken.Token);
cancellationToken.CancelAfter(TimeSpan.FromMilliseconds(1000)); // cancel after 1sec
await task;
Think
方法中,您应该添加对
CancellationToken.ThrowifcCancellationRequested的调用
调用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();
}
以及机器人本身:

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

}
class-TalkingBot
{
字符串输入=null;
int超时=0;
字符串asyncThnikResult=null;
公共字符串思考(字符串输入,int超时)
{
DateTime timeLimit=DateTime.Now.AddMillimes(超时);
这个输入=输入;
this.timeout=超时;
System.Threading.Thread Thread=新的System.Threading.Thread(新的System.Threading.ThreadStart(asynchnik));
thread.Start();
//在这种情况下,等待结果
while(string.IsNullOrEmpty(asyncThnikResult))
{
如果(时间限制调用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();
}
以及机器人本身:

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

}
class-TalkingBot
{
字符串输入=null;
int超时=0;
字符串asyncThnikResult=null;
公共字符串思考(字符串输入,int超时)
{
DateTime timeLimit=DateTime.Now.AddMillimes(超时);
这个输入=输入;
this.timeout=超时;
System.Threading.Thread Thread=新的System.Threading.Thread(新的System.Threading.ThreadStart(asynchnik));
thread.Start();
//在这种情况下,等待结果
while(string.IsNullOrEmpty(asyncThnikResult))
{

如果(timeLimit您可以将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();
}

您可以将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();
}

我认为他无法控制聊天机器人服务。否则,他可以将超时设置为think调用。他可以始终将该调用包装为Task。运行并使用取消令牌。Task.Run本身并不处理取消,它只允许您传递一个令牌,您可以检查自己。think是一个单独的阻塞调用,有时es花费的时间太长,因此一旦令牌启动,就没有机会检查令牌以取消它。Task.Run.Wait(超时)可能会工作,如果超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时超时Think调用的超时时间。他总是可以将该调用包装到Task中。运行并使用取消令牌。Task.Run本身不处理取消,它只允许您传递一个令牌,您可以自己检查。Think是一个单独的阻塞调用,有时会花费很长时间,因此没有机会检查令牌以取消它nce它已启动。任务。运行。等待(超时)可能会起作用,如果超时异常用完,这将抛出超时异常,然后他可以在处理程序中为超时异常写入错误消息。这不会起作用,
chatterBotSession.Think
返回字符串,只接受单个字符串作为输入。这是WinForms还是WPF应用程序?哪个.Net版本?这是WinForms还是WPF应用程序应用程序?哪个.Net版本?MSDN Ref:MSDN Ref: