Установить текст метки формы по таймеру из ссылки - PullRequest
0 голосов
/ 23 декабря 2018

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

Рядом с моей формой я использую класс AudioPlayer, который содержит ссылку на созданную форму.

В функции playAudio я хочу запустить таймер, который должен вызвать updateCurrTime, когда истечет время.(Для справки: я использую NAudio )

Функция, вызывающая таймер:

public bool playAudio()
    {
        if (waveOutDevice.PlaybackState == PlaybackState.Playing)
        {
            waveOutDevice.Pause();
            timer.Enabled = false;
            return false;
        }
        else if(waveOutDevice.PlaybackState == PlaybackState.Paused)
        {
            waveOutDevice.Play();
            timer.Enabled = true;
            return true;
        }
        else if(waveOutDevice.PlaybackState == PlaybackState.Stopped)
        {
            initPlayer(mu_path);
            waveOutDevice.Play();
            timer.Enabled = true;
            return true;
        }
        return false;
    }

И функция для обновления моей формы:

public void updateCurrTime()
    {
        while (waveOutDevice.PlaybackState == PlaybackState.Playing)
        {
            form1_ref.curr_time = (int)audioFileReader.CurrentTime.TotalSeconds;
        }
    }

Я определил таймер так:

            timer = new Timer();
        timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
        timer.Interval = 100;
    }

и OnTimedEvent так:

        private static void OnTimedEvent(object source, ElapsedEventArgs e)
    {
        self_ref.updateCurrTime();
    }

Я использую структуру getter / setter для текста метки:

        public int curr_time
    {
        get { return Convert.ToInt32(this.l_t_curr.Text); }
        set { this.l_t_curr.Text = value.ToString() + "s"; }
    }

Моя проблема в том, что я получаю сообщение об ошибке, потому что форма создается в другом потоке.Я сделал свое исследование, но я не понял, как реализовать BackGroundWorker или другие решения в моем случае.

Ответы [ 2 ]

0 голосов
/ 23 декабря 2018

Для обновления графического интерфейса пользователя из другого потока необходимо использовать Invoke или BeginInvoke.

Пример:

private void GuiUpdate(object sender, EventArgs e)
{
  if (this.InvokeRequired)
  {
    this.BeginInvoke((MethodInvoker)delegate
    {
      GuiUpdate(sender, e);
    });
    return;
  }

  // put here GUI updating code
}

Разница между Invoke или BeginInvoke составляет:

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

Используйте Invoke, когда вам нужно получить результат от функции или приоритетное обновление.В противном случае лучше использовать BeginInvoke.

0 голосов
/ 23 декабря 2018

С помощью подсказки Джуло я смог решить проблему.

public void updateCurrTime()
    {
        MethodInvoker methodInvokerDelegate = delegate ()
        { form1_ref.l_t_curr.Text = audioFileReader.CurrentTime.TotalSeconds.ToString(); };
        //form1_ref.curr_time = (int)audioFileReader.CurrentTime.TotalSeconds;

        //This will be true if Current thread is not UI thread.
        if (form1_ref.InvokeRequired)
            form1_ref.Invoke(methodInvokerDelegate);
        else
            methodInvokerDelegate();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...