Есть ли способ отменить неотменяемую задачу С#, не дожидаясь тайм-аута, если задача завершается раньше?

У меня есть метод, в котором я не контролирую (предположим, что он из другой библиотеки):

private static void DoWork()
{
    // I have no control over this method
    while (true)
    {
        Console.WriteLine("Still working");
    }
}

И я хочу подождать некоторое время (например, 20 секунд), и если задание не будет завершено за это время, чтобы остановить код.

Что я пробовал до сих пор:

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

  • Использование только класса Task не вариант, потому что я не могу остановить выполнение задачи без использования токена отмены

    var taskToWaitAndKill =
        Task.Factory.StartNew(DoWork);
    taskToWaitAndKill.Wait(20000); // 20 seconds
    // The task cannot be stopped (aborted) and still runs...
    
  • Использование класса Thread, его ожидание и прерывание - это не вариант, потому что мне нужно подождать все 20 секунд, прежде чем остановить код.

    var thread = new Thread(DoWork);
    thread.Start();
    Thread.Sleep(20000);
    thread.Abort();
    

Итак, мой вопрос: есть ли способ в C# ждать фиксированное количество миллисекунд для выполнения кода, и если код завершится раньше, не ждать больше?


person Nikolay Kostov    schedule 06.12.2015    source источник
comment
Вы должны прервать операцию? Или это может продолжаться в фоновом режиме, пока вы возобновляете свою работу?   -  person Yuval Itzchakov    schedule 06.12.2015
comment
См. если этот ответ поможет.   -  person Yuval Itzchakov    schedule 06.12.2015


Ответы (1)


Использование класса Thread, его ожидание и прерывание - это не вариант, потому что мне нужно подождать все 20 секунд, прежде чем остановить код.

Сделайте это по-другому, и вы можете сделать это:

var timeout = TimeSpan.FromSeconds(20);
var started = DateTime.UtcNow;
var thread = new Thread(DoWork);
thread.Start();
while (thread.IsAlive && DateTime.UtcNow - started < timeout)
{
    Thread.Sleep(10);
    // Do whatever here
}

// timeout occured, aborting
if (thread.IsAlive)
    thread.Abort();

Однако уничтожение потока с помощью Abort является опасной операцией. , может вызвать сюрпризы. Если вам действительно нужно выполнять чужие коды, которые вы не можете контролировать (например, сторонние плагины), вам следует создать AppDomain для них. В случае каких-либо ошибок (в том числе ThreadAbortException) вы можете безопасно выгрузить AppDomain.

person György Kőszeg    schedule 06.12.2015