Поток выполнения при использовании task.Wait в c # - PullRequest
1 голос
/ 27 мая 2019

У меня есть пример кода, приведенный ниже, в котором есть логика для отмены задачи более чем за 30 минут.
Метод1 вызывает Method2 и Method3, что занимает 15 минут и 10 минут, чтобы завершить соответственно. Я дал буфер 5 минут и установилТайм-аут на все исполнение как 30 минут.

public class Program
{
    static void Main()
    {
        Program p = new Program();
        var tokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(0.5));
        var token = tokenSource.Token;
        var task = Task.Factory.StartNew(() => {
            p.Method1(token);
        }, token);

        try
        {
            task.Wait();
        }
        catch (AggregateException e)
        {
            Console.WriteLine("Method1 did not finish within 1 mins :" + DateTime.Now);
        }
        finally
        {
            tokenSource.Dispose();
        }
        Console.ReadLine();
    }
    public bool Method1(CancellationToken token)
    {
        Console.WriteLine("Inside Method1 :" + DateTime.Now);
        Method2(token);
        return true;
    }
    public bool Method2(CancellationToken token)
    {
        try
        {
            token.ThrowIfCancellationRequested();

            Console.WriteLine("Inside Method2 begin :" + DateTime.Now);
            Thread.Sleep(60000); // In the actual code , this line is replaced with the line which executes for more than 1 min.To replicate it, I just made the Thread to sleep.
            if (token.IsCancellationRequested)
            {
                token.ThrowIfCancellationRequested();
            }
            Console.WriteLine("Inside Method2 end :" + DateTime.Now);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception in Method2");
            return false;

        }
    }
}

Теперь проблема, с которой я сталкиваюсь, заключается в том, что порядок выполнения, в котором выполняются методы, отличается от того, что я ожидал, когда общее выполнение занимает более 30 минут. Предположим, что выполнение метода 2требуется больше времени, чтобы закончить.
Ожидание:

Внутри Method1
Внутри Method2
Исключение в Method2
Method1 не завершился в течение 30 минут

Реальность:

Внутри Method1
Внутри Method2
Исключение в Method2

Какие изменения необходимыдолжно быть сделано, чтобы сделать поток выполнения, как ожидалось.Это вообще возможно?

В этом примере я привел только пример Method2.На самом деле есть 3-4 метода, которые выполняют некоторые типичные операции.Любой из них может занять некоторое время, чтобы выполнить.Таким образом, установка таймаута только для Method2 не решит проблему.

EDIT2

Я удалил старый код и заменил его тем, что было предложено в ответах, чтобы избежать путаницы.Вот, что я сделал, так это сделал поток спящим в течение 1 минуты, где время ожидания составляет всего 30 секунд.Вот что происходит, когда выполнение происходит в Thread.Sleep, оно ждет 60 секунд, а затем выдает исключение.Я хочу, чтобы он выдал исключение, как только истечет 30 секунд.

1 Ответ

0 голосов
/ 27 мая 2019

Код в Method2 продолжает выполняться даже после того, как истекло время ожидания - нет ничего, что автоматически останавливает его или вызывает исключение. То, что вы хотите сделать, называется отмены : вы хотите, чтобы тайм-аут активировал сигнал, который Method2 может время от времени проверять, чтобы он мог свернуть то, что он делает, или выдать исключение, если тайм-аут срабатывает.

Вместо указания времени ожидания для Wait создайте CancellationTokenSource на основе времени ожидания с new CancellationTokenSource(TimeSpan.FromMinutes(30)) и передайте его токен во все методы, выполняющиеся в задаче. Эти методы могут затем передать токен в любые методы async, которые они вызывают, и / или использовать методы / свойства токена, чтобы узнать, истекло ли время ожидания. Смотри здесь .

...