简体   繁体   中英

How to stop thread in C#?

Info: I'm creating game using C# in Visual Studio 2017

How can I stop music thread? Is it possible even from different form? I used this code to create thread which plays music in background

MediaPlayer bg;

public void main()
{
    IntializeComponent();
    Bg_music();
}

private void Bg_music()
{
    new System.Threading.Thread(() =>
    {
        bg = new System.Windows.Media.MediaPlayer();
        bg.Open(new System.Uri(path + "Foniqz_-_Spectrum_Subdiffusion_Mix_real.wav"));
        bg.Play();
    }).Start();                        
}

When I try to stop the thread using this code, it stops window which is currently open and music/thread keeps playing music

bg.Dispatcher.Invoke(() =>
{
    bg.Close();
});

also this didn't work

bg.Dispatcher.Invoke(() =>
{
    bg.Stop();
});

Assuming you really need a background thread (because the MediaPlayer it's non-blocking on WPF) you may want to use one of the following paths in C#:

  1. Use Cancelation Token & Tasks:

      MediaPlayer bg; readonly CancellationTokenSource tokenSource = new CancellationTokenSource(); public MainWindow() { InitializeComponent(); Bg_music(); } private void Bg_music() { Task.Run(() => { bg = new MediaPlayer(); bg.Open(new Uri(@"D:\\Songs\\201145-Made_In_England__Elton_John__320.mp3")); bg.Play(); bg.Play(); while (true) { if (tokenSource.Token.IsCancellationRequested) { bg.Stop(); break; } } }, tokenSource.Token); } private void ButtonBase_OnClick(object sender, RoutedEventArgs e) { tokenSource.Cancel(); } 

    }

or

  1. Use Events to communicate through Tasks. (Stop using threads, we have tasks now)

Cross-thread object access might be tricky.

Once you create MediaPlayer instance in another thread other than the UI thread, accessing this object inside the UI thread will throw InvalidOperationException since the object doesn't belong to UI thread.

    private void Bg_music()
    {
        bg = new System.Windows.Media.MediaPlayer();
        new System.Threading.Thread(() =>
        {
            bg.Dispatcher.Invoke(()=>{
                bg.Open(new System.Uri(path + "Foniqz_-_Spectrum_Subdiffusion_Mix_real.wav"));
                bg.Play();
            });

        }).Start();                        
    }

Now you don't have to use Dispatcher to stop the MediaPlayer when calling it inside the UI thread.

Edit: Even if the implemented method is not the best practice, still worth to be answered to advert some theorical information.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM