Как установить тайм-аут для метода

как установить тайм-аут для метода занятости + С#.

Ответы

Ответ 1

Хорошо, вот реальный ответ.

...

void LongRunningMethod(object monitorSync)
{
   //do stuff    
   lock (monitorSync) {
     Monitor.Pulse(monitorSync);
   }
}

void ImpatientMethod() {
  Action<object> longMethod = LongRunningMethod;
  object monitorSync = new object();
  bool timedOut;
  lock (monitorSync) {
    longMethod.BeginInvoke(monitorSync, null, null);
    timedOut = !Monitor.Wait(monitorSync, TimeSpan.FromSeconds(30)); // waiting 30 secs
  }
  if (timedOut) {
    // it timed out.
  }
}

   ...

Это объединяет две наиболее интересные части использования С#. Во-первых, для асинхронного вызова метода используйте делегат, у которого есть магия BeginInvoke.

Затем используйте монитор для отправки сообщения из LongRunningMethod обратно в ImpatientMethod, чтобы сообщить ему, когда он был сделан, или если он не слышал от него в течение определенного времени, просто сдайтесь на нем.

(p.s.- Просто шутите об этом, являясь реальным ответом. Я знаю, что есть 2 ^ 9303 способов скинуть кошку. Особенно в .Net)

Ответ 2

Вы не можете этого сделать, если вы не измените метод.

Существует два способа:

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

Самый очевидный, но, к сожалению, неправильный ответ, вы можете получить здесь: "Просто запустите метод в потоке и используйте Thread.Abort, если он слишком долго работал".

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

Также есть третий способ, когда вы выполняете метод в отдельном потоке, но после ожидания его завершения, и для этого требуется слишком много времени, вы просто говорите: "Я не буду ждать, пока он закончит, но просто отбросьте это". В этом случае метод все равно будет работать и, в конце концов, закончен, но этот другой поток, который его ждал, просто откажется.

Подумайте о третьем способе, как позвонить кому-то и попросить их обыскать их дом за ту книгу, которую вы одолжили им, и после того, как вы ожидаете на своем конце телефона в течение 5 минут, вы просто говорите "aw, chuck it" и вешайте вверх. В конце концов, другой человек найдет книгу и вернется к телефону, только чтобы заметить, что вы больше не заботитесь о результатах.

Ответ 3

В то время как ответ MojoFilter хорош, это может привести к утечкам, если "LongMethod" замерзает. Вы должны ЗАПИСАТЬ операцию, если вы больше не заинтересованы в результатах.

public void LongMethod()
{
    //do stuff
}

public void ImpatientMethod()
{
    Action longMethod = LongMethod; //use Func if you need a return value

    ManualResetEvent mre = new ManualResetEvent(false);

    Thread actionThread = new Thread(new ThreadStart(() =>
    {
        var iar = longMethod.BeginInvoke(null, null);
        longMethod.EndInvoke(iar); //always call endinvoke
        mre.Set();
    }));

    actionThread.Start();
    mre.WaitOne(30000); // waiting 30 secs (or less)
    if (actionThread.IsAlive) actionThread.Abort();
}

Ответ 4

Это старый вопрос, но теперь он имеет более простое решение, которое не было доступно тогда: Задачи!

Вот пример кода:

var task = Task.Run(() => LongRunningMethod());//you can pass parameters to the method as well
if (task.Wait(TimeSpan.FromSeconds(30)))
    return task.Result; //the method returns elegantly
else
    throw new TimeoutException();//the method timed-out

Ответ 5

Вы можете запустить этот метод в отдельном потоке и контролировать его и заставить его выйти, если он работает слишком долго. Хорошим способом, если вы можете назвать это как таковой, было бы разработать атрибут для метода в Опубликовать Sharp, чтобы наблюдательный код не был" t засоряя ваше приложение.

Я написал следующее в качестве примера кода (обратите внимание на часть кода примера, он работает, но может пострадать от проблем с многопоточным движением или если рассматриваемый метод захватывает ThreadAbortException, это сломает его):

static void ActualMethodWrapper(Action method, Action callBackMethod)
{
    try
    {
        method.Invoke();
    } catch (ThreadAbortException)
    {
        Console.WriteLine("Method aborted early");
    } finally
    {
        callBackMethod.Invoke();
    }
}

static void CallTimedOutMethod(Action method, Action callBackMethod, int milliseconds)
{
    new Thread(new ThreadStart(() =>
    {
        Thread actionThread = new Thread(new ThreadStart(() =>
        {
            ActualMethodWrapper(method, callBackMethod);
        }));

        actionThread.Start();
        Thread.Sleep(milliseconds);
        if (actionThread.IsAlive) actionThread.Abort();
    })).Start();
}

Со следующим вызовом:

CallTimedOutMethod(() =>
{
    Console.WriteLine("In method");
    Thread.Sleep(2000);
    Console.WriteLine("Method done");
}, () =>
{
    Console.WriteLine("In CallBackMethod");
}, 1000);

Мне нужно работать с моей читабельностью кода.

Ответ 6

Методы не имеют тайм-аутов в С#, если только ваш отладчик или ОС не уверены, что ваше приложение "зависает". Даже тогда обработка продолжается, и пока вы не убиваете приложение, возвращается ответ, и приложение продолжает работать.

Вызовы в базах данных могут иметь тайм-ауты.

Ответ 7

Не могли бы вы создать Асинхронный метод, чтобы вы могли продолжать делать другие вещи, пока завершается "занятый" метод?

Ответ 8

Я регулярно пишу приложения, где мне приходится синхронизировать критически важные задачи на разных платформах. Если вы можете избежать thread.abort, вы должны. См. http://blogs.msdn.com/b/ericlippert/archive/2010/02/22/should-i-specify-a-timeout.aspx и http://www.interact-sw.co.uk/iangblog/2004/11/12/cancellation для рекомендаций о том, когда thread.abort подходит. Вот концепция, которую я реализую:

  • Выборочное исполнение: Выполняется только в том случае, если существует разумная вероятность успеха (основанная на способности соответствовать тайм-ауту или вероятности результата успеха по сравнению с другими поставленными в очередь элементами). Если вы разбиваете код на сегменты и знаете приблизительное ожидаемое время между кусками задач, вы можете предсказать, следует ли пропустить дальнейшую обработку. Общее время можно измерить, обернув задачи объекта bin рекурсивной функцией для вычисления времени или имея класс контроллера, который наблюдает за рабочими, чтобы знать ожидаемое время ожидания.
  • Выборочное сиротство: ждать только возвращения, если есть разумные шансы на успех. Индексированные задачи запускаются в управляемой очереди. Задачи, которые превышают их тайм-аут или рискуют вызвать другие таймауты, становятся сиротами, а вместо них возвращается нулевая запись. Более длинные запущенные задачи могут быть завернуты в асинхронные вызовы. См. Пример оболочки асинхронного вызова: http://www.vbusers.com/codecsharp/codeget.asp?ThreadID=67&PostID=1
  • Условный выбор: аналогично выборочному исполнению, но на основе группы вместо отдельной задачи. Если многие из ваших задач взаимосвязаны, так что один успех или неудача делают ненужную дополнительную обработку, создайте флаг, который проверяется до начала выполнения и снова, прежде чем начинаются подзадачи. Это особенно полезно, если вы используете функции parallel.for или других таких задач в очереди concurrency.