c # определенная последовательность таймера - PullRequest
0 голосов
/ 20 ноября 2018

Я хочу сделать последовательность временных событий для мигающего индикатора азбуки Морзе.Программа должна работать, пока мигает индикатор.

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

Пример последовательности

  • Выключить свет 3000 мс
  • Включить свет 1200 мс
  • Выключить свет 500 мс
  • Включить свет 400 мс
  • Выключить свет 500 мс
  • Индикатор на 1200 мс
  • Индикатор выключен на 500 мс
  • Индикатор на 400 мс
  • начать заново

Я попробовал этот код, но он только зависает программа

private void Morse()
{
    System.Timers.Timer MorseCode = new System.Timers.Timer(3000);
    MorseCode.Elapsed += new ElapsedEventHandler(long);
    MorseCode.Elapsed += new ElapsedEventHandler(short);
    MorseCode.Elapsed += new ElapsedEventHandler(long);
    MorseCode.Elapsed += new ElapsedEventHandler(short);

    void short(object sender, ElapsedEventArgs e)
    {
        MorseCode.Elapsed += new ElapsedEventHandler(ColorChange);
        MorseCode.Interval = 400;
        MorseCode.Elapsed += new ElapsedEventHandler(ColorChange);
        MorseCode.Interval = 500;
    }
    void long(object sender, ElapsedEventArgs e)
    {
        MorseCode.Elapsed += new ElapsedEventHandler(ColorChange);
        MorseCode.Interval = 1200;
        MorseCode.Elapsed += new ElapsedEventHandler(ColorChange);
        MorseCode.Interval = 500;
    }
    void ColorChange(object sender, ElapsedEventArgs e)
    {
        if(BlinkLight.BackColor == Color.Gray)
        {
            BlinkLight.BackColor = Color.DodgerBlue;
        }
        else
        {
            BlinkLight.BackColor = Color.Gray;
        }
    }    
}

Так как мне сделать последовательность с разными временами для мигающего света?

Ответы [ 3 ]

0 голосов
/ 20 ноября 2018

Для этого вы можете использовать библиотеку параллельных задач, она включена в .NET 4 и выше.Это даст аккуратный читаемый код, подобный следующему:

private void Morse()
{
    BlinkShort().ContinueWith(          //
        BlinkShort).ContinueWith(       //  S
        BlinkShort).ContinueWith(       //
        BlinkLong).ContinueWith(        //
        BlinkLong).ContinueWith(        //  O
        BlinkLong).ContinueWith(        // 
        BlinkShort).ContinueWith(       //
        BlinkShort).ContinueWith(       //  S
        BlinkShort);                    // 
}

Пример реализации вспомогательных методов:

private Task BlinkShort(Task previousTask = null)
{
    var action = new Action(() =>
    {
        SetColorSafe(true);
        Task.Delay(400).Wait();
        SetColorSafe(false);
        Task.Delay(500).Wait();
    });
    var t = Task.Run(action);
    if (previousTask != null) // already threaded
    {
        t.Wait();
    }

    return t;
}
private Task BlinkLong(Task previousTask = null)
{
    var action = new Action(() =>
    {
        SetColorSafe(true);
        Task.Delay(1200).Wait();
        SetColorSafe(false);
        Task.Delay(500).Wait();
    });
    var t = Task.Run(action);
    if (previousTask != null) // already threaded
    {
        t.Wait();
    }

    return t;
}

private void SetColorSafe(bool on)
{
    if (InvokeRequired)
    {
        Invoke(new Action(() => {
            SetColorSafe(on);
        }));
        return;
    }
    if (on)
    {
        BackColor = Color.DodgerBlue;
    }
    else
    {
        BackColor = Color.Gray;
    }
}
0 голосов
/ 20 ноября 2018

Мне нравится Решение загадки .Если вы знаете System.Reactive, это выбор goog.

Это простое решение с использованием асинхронной задачи.
Я перехожу к асинхронному методу:
- List<Tuple<int, int>>который представляет пробелы и длительности сигналов
- Control - отношение, которое будет служить визуальным выходным сигналом
- CancellationToken, используемое для сигнализации о завершении задачи.

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

Обратите внимание, что я немного изменил последовательность и время.Пауза между каждой итерацией последовательности находится в конце последовательности, поэтому он запускает сигнал немедленно, а затем приостанавливает его после выполнения каждой последовательности.

Когда выдается запрос на отмену, Задача будетзавершите последовательность перед отменой:
if (token.IsCancellationRequested) return; проверяется только после завершения последовательности, чтобы избежать путаницы с таймингами.Но это можно изменить, чтобы проверять отмену после каждой длительной паузы.

CancellationTokenSource source;
CancellationToken token;

private void button1_Click(object sender, EventArgs e)
{
    if (source != null)
    {
        source.Cancel();
        source.Dispose();
        source = null;
        return;
    }

    source = new CancellationTokenSource();
    token = source.Token;
    List<Tuple<int, int>> MorseCodeSequence = new List<Tuple<int, int>>()
    {
        new Tuple<int, int>(1200, 200),
        new Tuple<int, int>(400, 200),
        new Tuple<int, int>(1200, 200),
        new Tuple<int, int>(400, 2000)
    };

    Task.Run(()=> MorseSequence(MorseCodeSequence, this.btnMorse, token));
}

public async Task MorseSequence(List<Tuple<int, int>> MorseSequence, Control MorseCodeOutputObject, CancellationToken token)
{
    while (true)
    {
        foreach (Tuple<int, int> MorseTiming in MorseSequence)
        {
            MorseCodeOutputObject.BeginInvoke(new MethodInvoker(() =>
                { MorseCodeOutputObject.BackColor = Color.Cyan; }));
            await Task.Delay(MorseTiming.Item1);
            MorseCodeOutputObject.BeginInvoke(new MethodInvoker(() =>
                { MorseCodeOutputObject.BackColor = Color.Gray; }));
            await Task.Delay(MorseTiming.Item2);
        }
        if (token.IsCancellationRequested) return;
    };
}

Последовательность SOS

List<Tuple<int, int>> SOSMorseSequence = new List<Tuple<int, int>>()
{
    new Tuple<int, int>(400, 200),
    new Tuple<int, int>(400, 200),
    new Tuple<int, int>(400, 300),
    new Tuple<int, int>(1200, 200),
    new Tuple<int, int>(1200, 200),
    new Tuple<int, int>(1200, 300),
    new Tuple<int, int>(400, 200),
    new Tuple<int, int>(400, 200),
    new Tuple<int, int>(400, 2000),
};
0 голосов
/ 20 ноября 2018

Используйте для этого Microsoft Reactive Framework - NuGet "System.Reactive.Windows.Forms".

Тогда вы можете сделать это:

int[] timings = new [] { 3000, 1200, 500, 400, 500, 1200, 500, 400 };

IObservable<System.Drawing.Color> sequence =
    Observable
        .Generate(
            0,
            x => x < timings.Length,
            x => x + 1,
            x => x % 2 == 1 ? System.Drawing.Color.DodgerBlue : System.Drawing.Color.Gray,
            x => TimeSpan.FromMilliseconds(timings[x]));

IDisposable subscription =
    sequence
        .Repeat()
        .ObserveOn(BlinkLight)
        .Subscribe(color => BlinkLight.BackColor = color);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...