user3448806
user3448806

Reputation: 907

The DispatcherTimer still tick event after Stop() and set to null

I'm writing an app to listen music and watch video. In app, I have these 2 pages: 1 to play the audio playback agent (APA) - Page A, and one to play the video (using MediaElement) - Page B. While WP8 has an bug with the APA ( which I've asked here here (which I found a solution - stop the APA twice after and before when the MediaElement plays and closes).

Problem is, at the A page, I used an DispatcherTimer tick every second to check the APA instance positon, and when I leave this page, I have a funtion to stop this DispatcherTimer .

Even that, if I navigated to and from page A for a several times, and then navigate to page B, after 1 Second the app thrown an exception at the if (BackgroundAudioPlayer.Instance.PlayerState == .... It means that the DispatcherTimer still tick ????? How can I force to stop this :(


I posted all code which related to the DispatcherTimer here :

public DetailSongPage()
    {
        InitializeComponent();
        this.DataContext = App.Model;            
        BackgroundAudioPlayer.Instance.PlayStateChanged += APA_Instance_PlayStateChanged;                        
    }
DispatcherTimer timer = null;

private void APA_Instance_PlayStateChanged(object sender, EventArgs e)
    {
        if (BackgroundAudioPlayer.Instance.PlayerState == PlayState.Playing)
        {                
            UpdateTracking();
        }              
    }
protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);                           
        if (BackgroundAudioPlayer.Instance.PlayerState == PlayState.Playing || BackgroundAudioPlayer.Instance.PlayerState == PlayState.Paused)
        {   
            UpdateTracking();   
        }
    }
protected override void OnNavigatedFrom(NavigationEventArgs e)
    { 
        base.OnNavigatedFrom(e);
        timer.Stop();            
        timer.Tick -= timer_Tick;
        timer = null;            
    }
private void UpdateTracking()
    {
        sldTracking.Maximum = BackgroundAudioPlayer.Instance.Track.Duration.TotalMilliseconds;
        tbMaxTime.Text = string.Format(@"{0:mm\:ss}",BackgroundAudioPlayer.Instance.Track.Duration);
        // ^ these 2 lines update the UI for the slider and textblock 

        if (timer == null)
        {
            timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromMilliseconds(1000);
            timer.Tick += timer_Tick;
            timer.Start();
        }  
    }
    private void timer_Tick(object sender, EventArgs e)
    {
        if (this.timer != null)
        {
            try
            {                   
                if (BackgroundAudioPlayer.Instance.PlayerState == PlayState.Playing || BackgroundAudioPlayer.Instance.PlayerState == PlayState.Paused)
                {
                    sldTracking.Value = BackgroundAudioPlayer.Instance.Position.TotalMilliseconds;
                    tbCurrentTime.Text = string.Format(@"{0:mm\:ss}", BackgroundAudioPlayer.Instance.Position);
                }
            }
            catch
            {
                return;
            }
        }
    }

Upvotes: 2

Views: 1294

Answers (1)

Mark
Mark

Reputation: 449

You could implement the IDispose in your class, in this implementation, stop the timer. Then call the Dispose whenever you leave the page. In the Dispose, you should write something like:

timer?.Stop();

Upvotes: 0

Related Questions