如何限制C Sharp中函数的执行时间?

发布于 2024-12-04 21:21:32 字数 115 浏览 0 评论 0原文

我有一个问题。我正在编写一个基准测试,并且我有一个函数可以在 2 秒内或约 5 分钟后完成(取决于输入数据)。如果该函数执行时间超过 3 秒,我想停止该函数...

我该怎么做?

多谢!

I've got a problem. I'm writing a benchmark and I have a function than is either done in 2 seconds or after ~5 minutes(depending on the input data). And I would like to stop that function if it's executed for more than 3 seconds...

How can I do it?

Thanks a lot!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

匿名。 2024-12-11 21:21:32

嗯...,我有同样的问题,在阅读了这里的所有答案和引用的博客后,我解决了这个问题,

它让我在时间限制下执行任何代码块,声明包装方法

    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

Well..., I had the same question, and after reading all the answers here and the referred blogs, I settled for this,

It Lets me execute any block of code with a time limit, Declare the wrapper method

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

And use that to wrap any block of code like this

    // code here

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

    //More code
偷得浮生 2024-12-11 21:21:32

最好的方法是您的函数可以经常检查其执行时间,以决定停止它花费的时间太长。

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

The best way would be that your function can check its execution time often enough to decide to stop it it takes too long.

If this is not the case, then run the function in a separate thread. In your main thread start a 3 seconds timer. When timer elapses, kill the separate thread using Thread.Abort() (of course unless the function is already over). See sample code and preacuations of usage in the function docs.

蒗幽 2024-12-11 21:21:32

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

if (stopwatch.ElapsedMilliseconds >= 3000) { 
     stopwatch.Stop();
     // or 
     stopwatch.Reset(); 
     return;
 } 

提示:您可以用手输入一次,然后按 Ctrl+C 复制,然后按 Ctrl+V 粘贴)。如果该函数使用递归,为了节省内存,请创建 Stopwatch 全局实例,而不是首先将其创建为本地实例,如果它没有在代码开头运行,则启动它。您可以通过 Stopwatch 类的 IsRunning 知道这一点。之后询问经过的时间是否超过3秒,如果是(true)则停止或重置秒表,并使用return关键字停止递归循环,非常如果您的函数主要由于递归而不是循环而持续很长时间,那么函数的良好开端。确实如此。正如你所看到的,这非常简单,我测试了这个解决方案,结果表明它有效!自己尝试一下吧!

The best way in C# to stop function in middle is the return keyword in function, but how do I know when to use the return keyword to stop the function in middle, after it lasts at least 3 seconds? The Stopwatch class from System.Diagnostics is the answer. This complicated function that lasts between 2 seconds to 5 minutes (depending on the input data) logically uses many loops, and maybe even recursion, so my solution for you is that, at the first line code of that function, create an instance of Stopwatch using System.Diagnostics with the new keyword, start it by calling the Start() function of the Stopwatch class, and in for each loop and loop, at the beginning, add the following code:

if (stopwatch.ElapsedMilliseconds >= 3000) { 
     stopwatch.Stop();
     // or 
     stopwatch.Reset(); 
     return;
 } 

(tip: you can type it with hands once, copy it Ctrl+C, and then just paste it Ctrl+V). If that function uses recursion, in order to save memory, make the Stopwatch global instance rather than creating it as local instance at first, and start it if it does not running at the beginning of the code. You can know that with the IsRunning of the Stopwatch class. After that ask if elapsed time is more than 3 seconds, and if yes (true) stop or reset the Stopwatch, and use the return keyword to stop the recursion loop, very good start in function, if your function lasts long time due mainly recursion more than loops. That it is. As you can see, it is very simple, and I tested this solution, and the results showed that it works! Try it yourself!

泅人 2024-12-11 21:21:32
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-ac-function-to-run-for/

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

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

    var delayInMilliseconds = randomNumber * 1000;

    Task.Delay(delayInMilliseconds).Wait();

    return randomNumber;
}

And

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.");
}

it work for me!
Source: https://jeremylindsayni.wordpress.com/2016/05/28/how-to-set-a-maximum-time-to-allow-a-c-function-to-run-for/

作死小能手 2024-12-11 21:21:32

您可以使用 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 与其他线程通信,其结果是不再需要,因此它可以优雅地停止。

问候格特-扬

You can use the fork/join pattern, in the Task Parallel Library this is implemented with 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");
}

This will start the other task on a seperate thread, and then wait for 3000 milliseconds for it to finish. If it did finish within the timeout, it return true, else false so you can use that to decide what to do next.

You can use a CancellationToken to communicate to the other thread that it result is no longer needed so it can stop gracefully.

Regards Gert-Jan

眼眸印温柔 2024-12-11 21:21:32

可以在单独的线程中执行函数并使用 Thread.Join(毫秒超时):

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
}

It is possible to execute a function in a separate thread and limit its execution with 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
}
思慕 2024-12-11 21:21:32

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

Run this function in thread and kill it after 3 seconds or check elapsed time inside this function(I think it's loop there).

最美不过初阳 2024-12-11 21:21:32

使用带有高性能计数器的操作系统回调,然后终止线程(如果存在)

Use an OS callbacks with a hi performance counter, then kill your thread, if exists

隔岸观火 2024-12-11 21:21:32

由于 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< /a>

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

Since C# and .net framework are not real-time environments, you can't guarantee even the 3 seconds count. Even if you were to get close to that, you would still have to call the

if(timeSpan > TimeSpan.FromSeconds(3) then goto endindentifier; before every other call in the method.

All this is just wrong so no, there is just no reliable way to do it from what I know.

Although you can try this solution

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

but I just wouldn't do such things in .net application.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文