如何在c sharp中限制函数的执行时间?

时间:2011-09-14 08:48:49

标签: c# execution-time time-limiting

我遇到了问题。我正在写一个基准测试,我有一个功能,而不是在2秒或大约5分钟后完成(取决于输入数据)。如果执行时间超过3秒,我想停止该功能......

我该怎么做?

非常感谢!

9 个答案:

答案 0 :(得分:48)

嗯......,我有同样的问题,在阅读了这里的所有答案和推荐的博客后,我为此付出了代价,

它允许我执行带有时间限制的任何代码块,声明包装器方法

    public static bool ExecuteWithTimeLimit(TimeSpan timeSpan, Action codeBlock)
    {
        try
        {
            Task task = Task.Factory.StartNew(() => codeBlock());
            task.Wait(timeSpan);
            return task.IsCompleted;
        }
        catch (AggregateException ae)
        {
            throw ae.InnerExceptions[0];
        }   
    }

并使用它来包装像这样的任何代码块

    // code here

    bool Completed = ExecuteWithTimeLimit(TimeSpan.FromMilliseconds(1000), () =>
    {
         //
         // Write your time bounded code here
         // 
    });

    //More code

答案 1 :(得分:5)

最好的方法是你的函数可以经常检查它的执行时间,以决定停止它需要太长时间。

如果不是这种情况,则在单独的线程中运行该函数。在你的主线程中启动一个3秒计时器。当计时器过去时,使用Thread.Abort()终止单独的线程(当然除非该功能已经结束)。请参阅函数文档中的示例代码和使用前预备。

答案 2 :(得分:3)

您可以使用fork / join模式,在任务并行库中使用Task.WaitAll()

实现
using System.Threading.Tasks;

void CutoffAfterThreeSeconds() {

    // start function on seperate thread
    CancellationTokenSource cts = new CancellationTokenSource();
    Task loop = Task.Factory.StartNew(() => Loop(cts.Token));

    // wait for max 3 seconds
    if(Task.WaitAll(new Task[]{loop}, 3000)){
       // Loop finished withion 3 seconds
    } else {
       // it did not finish within 3 seconds
       cts.Cancel();           
    }        
}

// this one takes forever
void Loop() {
    while (!ct.IsCancellationRequested) {
        // your loop goes here
    }
    Console.WriteLine("Got Cancelled");
}

这将在单独的线程上启动另一个任务,然后等待3000毫秒才能完成。如果它在超时内完成,则返回true,否则返回false,以便您可以使用它来决定下一步该做什么。

您可以使用CancellationToken与其他线程进行通信,不再需要它,以便它可以正常停止。

关心Gert-Jan

答案 3 :(得分:3)

C#在中间停止函数的最佳方法是函数中的return关键字,但是我怎么知道何时使用return关键字在中间停止函数,在它持续之后至少3秒?来自Stopwatch的{​​{1}}类就是答案。这个复杂的函数持续2秒到5分钟(取决于输入数据)逻辑上使用许多循环,甚至可能是递归,所以我的解决方案是,在该函数的第一行代码中,创建一个{的实例{1}} System.Diagnostics使用Stopwatch关键字,通过调用Stopwatch类的System.Diagnostics函数启动它,并在每个循环和循环中,在开头添加以下内容代码:

new

(提示:您可以用手键入一次,将其复制为Ctrl + C,然后将其粘贴到Ctrl + V)。如果该函数使用递归,为了节省内存,请创建秒表全局实例,而不是首先将其创建为本地实例,如果它没有在代码的开头运行,则启动它。您可以使用秒表类的Start()知道。之后询问是否经过的时间超过3秒,如果是(if (stopwatch.ElapsedMilliseconds >= 3000) { stopwatch.Stop(); // or stopwatch.Reset(); return; } )停止或重置秒表,并使用IsRunning关键字来停止递归循环,那么函数启动非常好,如果你的函数持续很长时间,主要是因为递归而不是循环。这是。正如您所看到的,它非常简单,我测试了这个解决方案,结果表明它有效!亲自试试吧!

答案 4 :(得分:1)

private static int LongRunningMethod()
{
    var r = new Random();

    var randomNumber = r.Next(1, 10);

    var delayInMilliseconds = randomNumber * 1000;

    Task.Delay(delayInMilliseconds).Wait();

    return randomNumber;
}

var task = Task.Run(() =>
{
    return LongRunningMethod();
});

bool isCompletedSuccessfully = task.Wait(TimeSpan.FromMilliseconds(3000));

if (isCompletedSuccessfully)
{
    return task.Result;
}
else
{
    throw new TimeoutException("The function has taken longer than the maximum time allowed.");
}

它为我工作! 来源:https://jeremylindsayni.wordpress.com/2016/05/28/how-to-set-a-maximum-time-to-allow-a-c-function-to-run-for/

答案 5 :(得分:0)

在线程中运行此函数并在3秒后将其终止检查此函数内的已用时间(我认为它是循环)。

答案 6 :(得分:0)

由于C#和.net框架不是实时环境,因此即使是3秒计数也无法保证。即使你接近这一点,你仍然需要调用

if(timeSpan > TimeSpan.FromSeconds(3) then goto endindentifier;在方法中的每次其他调用之前。

所有这一切都是错的所以不,没有可靠的方法可以从我所知道的那样做。

虽然你可以试试这个解决方案

https://web.archive.org/web/20140222210133/http://kossovsky.net/index.php/2009/07/csharp-how-to-limit-method-execution-time

但我不会在.net应用程序中做这些事情。

答案 7 :(得分:0)

使用具有hi性能计数器的OS回调,然后终止你的线程(如果存在)

答案 8 :(得分:0)

可以在单独的线程中执行函数并使用 Thread.Join(millisecondsTimeout) 限制其执行:

using System.Threading;

Thread workThread = new Thread(DoFunc);
workThread.Start(param);

if (!workThread.Join(3000))
{
    // DoFunc() took longer than 3 seconds. Thread was aborted
}

private void DoFunc(object param)
{
    // do some long work
}