Как ограничить время выполнения функции в Си-Шарп?

У меня проблема. Я пишу тест, и у меня есть функция, которая выполняется за 2 секунды или через ~5 минут(в зависимости от входных данных). И я хотел бы, чтобы остановить эту функцию, если она выполняется более 3 секунд...

Как я могу это сделать?

Спасибо большое!

7 ответов


лучшим способом было бы то, что ваша функция может проверять свое время выполнения достаточно часто, чтобы решить остановить его.

Если это не так, запустите функцию в отдельном потоке. В главном потоке запустите таймер на 3 секунды. Когда таймер истекает, убейте отдельный поток, используя нить.Abort () (конечно, если функция уже не закончена). Увидеть пример кода и preacuations использования в функции "документы".


хорошо..., У меня был тот же вопрос, и после прочтения всех ответов здесь и упомянутых блогов, я остановился на этом,

Это позволяет мне выполнить любой блок кода с ограничением по времени, объявите метод обертки

    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

вы можете использовать шаблон fork/join, в параллельной библиотеке задач это реализовано с помощью задач.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, else false, поэтому вы можете использовать это, чтобы решить, что делать дальше.

вы можете использовать CancellationToken для связи с другим потоком, что это результат нет нужно больше времени, чтобы он мог остановиться изящно.

С Уважением Герт-Ян


лучший способ в C# остановить функцию посередине-это return ключевое слово в функции, но как узнать, когда использовать return ключевое слово, чтобы остановить функцию посередине, после того, как она длится не менее 3 секунд? The Stopwatch класс System.Diagnostics ответ. Эта сложная функция, которая длится от 2 секунд до 5 минут (в зависимости от входных данных), логически использует много циклов и, возможно, даже рекурсию, поэтому мое решение для вас заключается в том, что в первой строке кода этой функции создайте пример Stopwatch используя System.Diagnostics С new ключевое слово, запустите его, вызвав Start() функция класса секундомера, и для каждого цикла и цикла, в начале, добавьте следующий код:

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

(совет: вы можете ввести его руками один раз, скопировать его Ctrl+C, а затем просто вставить его Ctrl+V). Если эта функция использует рекурсию, чтобы сохранить память, сделайте глобальный экземпляр секундомера, а не сначала создайте его как локальный экземпляр, и запустите его, если это не так запуск в начале кода. Вы можете знать, что с IsRunning класса секундомер. После этого спросите, прошло ли время более 3 секунд, и если да (true) остановите или сбросьте секундомер и используйте return ключевое слово, чтобы остановить цикл рекурсии, очень хороший старт в функции, если ваша функция длится долго из-за рекурсии больше, чем циклов. Что это. Как видите, это очень просто, и я протестировал это решение, и результаты показали, что оно работает! Попробовать его себя!


запустите эту функцию в потоке и убейте ее через 3 секунды или проверьте прошедшее время внутри этой функции (я думаю, что это цикл).


используйте обратные вызовы ОС со счетчиком производительности hi, а затем убейте свой поток, если он существует


Так как C# и .net framework не являются средами реального времени, вы не можете гарантировать даже количество 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-приложении.