Вопрос

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

Это было полезно?

Решение

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

...

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

   ...

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

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

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

Другие советы

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

Есть два способа:

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

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

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

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

    Думайте о третьем способе, как о том, чтобы позвонить кому-нибудь и попросить его найти в их доме ту книгу, которую вы одолжили ему, и после того, как вы подождете 5 минут на своем конце телефона, вы просто скажете «ау, бросьте его» и вешать трубку. В конце концов, этот другой человек найдет книгу и вернется к телефону, только чтобы заметить, что вы больше не заботитесь о результате.

  • Хотя ответ 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();
    }
    

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

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

    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
    

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

    Я написал следующее в качестве примера кода (обратите внимание на фрагмент кода примера, он работает, но может иметь проблемы с многопоточностью, или если рассматриваемый метод перехватывает исключение 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);
    

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

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

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

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

    Я регулярно пишу приложения, в которых мне приходится синхронизировать критичные по времени задачи на разных платформах.Если вы можете избежать 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.Вот концепция, которую я реализую:

    • Выборочное выполнение:Запускайте только в том случае, если существует разумный шанс на успех (основанный на способности уложиться в тайм-аут или вероятности успешного результата относительно других элементов, поставленных в очередь).Если вы разбиваете код на сегменты и примерно знаете ожидаемое время между фрагментами задачи, вы можете предсказать, следует ли вам пропустить дальнейшую обработку.Общее время может быть измерено путем обертывания задач object bin рекурсивной функцией для вычисления времени или с помощью класса контроллера, который следит за рабочими, чтобы узнать ожидаемое время ожидания.
    • Выборочное сиротство:Ждите возврата только в том случае, если существуют разумные шансы на успех.Индексированные задачи выполняются в управляемой очереди.Задачи, которые превышают время ожидания или рискуют вызвать другие тайм-ауты, отбрасываются, и вместо них возвращается нулевая запись.Более длительно выполняющиеся задачи могут быть обернуты в асинхронные вызовы.Смотрите пример оболочки асинхронного вызова: http://www.vbusers.com/codecsharp/codeget.asp ?ThreadId=67иpostID=1
    • Условный отбор:Аналогично выборочному выполнению, но на основе групповой, а не индивидуальной задачи.Если многие из ваших задач взаимосвязаны таким образом, что один успех или неудача делают дополнительную обработку неактуальной, создайте флаг, который проверяется перед началом выполнения и еще раз перед началом длительных подзадач.Это особенно полезно, когда вы используете parallel.for или другие подобные задачи параллелизма в очереди.
    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top