2

Нужно чтобы переменная proverkaTimera менялась в необходимом интервале времени с false на true и бесконечный цикл заходил бы в тело условия if (proverkaTimera)

Пробовал так и как в ответе ниже от trydex:

private void Algoritm()
{
    bool proverkaTimera = false;

    var timer = new DispatcherTimer();
    timer.Tick += Timer_Tick;
    timer.Interval = new TimeSpan(0, 0, 10, 0, 0);
    timer.Start();

    for (;;)
    {
       if (proverkaTimera)
       {
          ...
          proverkaTimera = false;
       }

       ...
    }
}

private void Timer_Tick(object sender, EventArgs e)
{
   proverkaTimera = true;
}

Ещё пробовал так, но в этом случае, откладывается выполнение остальной части когда пока пока не выполнится сам блок if.

private async void Algoritm()
{
    bool timerTick = false;

    for (;;)
    {

       timerTick = await Timer();

       if (timerTick)
       {
          ...
          timerTick = false;
       }

       ...
    }
}

private async Task<bool> Timer() 
{
        await Task.Delay(10000);
    return true;
}
Xzizz
  • 1,592
  • А в чем проблема, собственно? – Андрей NOP Oct 05 '18 at 20:19
  • 2
    @АндрейNOP: думаю ТС не знает о лямбдах, которые могут захватывать данные. –  Oct 05 '18 at 20:20
  • 1
    Разве при таком цикле for (;;) событие таймера вызовется? –  Oct 05 '18 at 20:21
  • @АндрейNOP проблема в том, что в таком виде Timer_Tick не знает о переменой – Xzizz Oct 05 '18 at 20:22
  • @Vipz Это-то как раз не проблема - сделайте переменную членом класса. –  Oct 05 '18 at 20:24
  • А зачем вам этот таймер? Что за алгоритм у вас? – tym32167 Oct 05 '18 at 20:30
  • 1
    https://ru.stackoverflow.com/q/615113/10105 – VladD Oct 05 '18 at 20:32
  • @Igor как это делается на моём примере ? – Xzizz Oct 06 '18 at 16:14

3 Answers3

1

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

То есть вместо создания отдельного обработчика события таким образом:

timer.Tick += Timer_Tick; 

мы можем подписать лямбда-выражение вот так:

timer.Tick += (s, e) => { proverkaTimera = true;};

О замыканиях можете почитать здесь.


Также можно вместо локальной переменной сделать поле или свойство, тогда вы сможете к ней обращаться из вашего метода Timer_Tick в текущей реализации.

То есть ваш класс видоизменится до такого:

class Example
{
    private bool proverkaTimera;

    private void Algoritm()
    {
        proverkaTimera = false;

        //Остальной код
    }

    private void Timer_Tick(object sender, EventArgs e)
    {
        proverkaTimera = true;
    }
}

trydex
  • 3,742
  • несколько раз пробовал делать это, но не резу бесконечный цикл не зашёл в тело if (proverkaTimera) – Xzizz Oct 09 '18 at 14:35
  • 2
    @Vipz, Это уже другой вопрос и об этом вам также говорили в комментариях. Событие не сработает т.к. поток занят бесконечным циклом. Отредактируйте ваш вопрос и опишите, что конкретно вы хотите сделать. – trydex Oct 09 '18 at 14:36
  • Я написал прям под кодом что мне нужно. – Xzizz Oct 09 '18 at 14:37
  • 2
    @Vipz, Я имел ввиду опишите картину в общем, что должен делать ваш метод?. Пока все выглядит так, что вы делаете в корне не верно. От бесконечного цикла нужно, скорее всего, нужно избавляться. – trydex Oct 09 '18 at 14:40
1

Я не совсем понимаю, почему все зациклились :) на лямбдах и замыканиях. Замыкание, конечно, удобно в данном случае, но член класса тоже сработает. Гораздо хуже здесь то (если я правильно понимаю, как работает DispatcherTimer), что плотный цикл не даст вызваться событию таймера.

Используйте System.Threading.Timer вместо DispatcherTimer и

bool proverkaTimera = false;

private void Algoritm()
{
  proverkaTimera = false;
  ...
  • Здорово, спасибо Вам ! А то перепробовал абсолютно каждый комментарий и всё не выходило, думал уже руки опустятся. Просто что не загуглю, везде DispatcherTimer используется, а с System.Threading.Timer всё просто, передал какой метод нужно использовать, передал переменную (правда получается что глобальную), указал интервал и всё работает как надо ! – Xzizz Oct 09 '18 at 15:36
  • 1
    @Vipz Я рад, что код заработал. Помните, что событие таймера, выполняемое в отдельном потоке, накладывает дополнительные требования к коду в этом событии. Доступ к элементам GUI должен быть синхронизирован с основным потоком. –  Oct 09 '18 at 15:42
  • Да, я сейчас подробнее про него почитаю, чтобы знать с чем имею дело. – Xzizz Oct 09 '18 at 15:46
1

Нет никакого смысла в таймере, который всего лишь устанавливает переменную! Если вам нужно отслеживать наступление некоторого момента времени - то для этих целей существует класс CancellationTokenSource:

using (var cts = new CancellationTokenSource(TimeSpan.FromMinutes(10)))
{
    for(;;) 
    {
        if (cts.IsCancellationRequested)
        {
            // 10 минут прошли
        }
    }
}

Бонусом идет возможность дождаться наступления события

ctx.Token.WaitHandle.WaitOne();

а также получить сигнал о его наступлении используя метод Register.

Pavel Mayorov
  • 58,537