In my class
Clicker.cs
, I am attempting to play a sound using a MediaPlayer
. However, whenever I call the method to toggle off the MediaPlayer
, I get the error that the calling thread cannot access this object because a different thread owns it. This code works fine in MainWindow.xaml.cs
, but it does not work in Clicker.cs
. I found similar problems online, and the fix was to use Dispatcher.Invoke()
. However, this did not work. The error specifically happens when StopSoundClicker() is called. My code is below:
private static MediaPlayer player = new MediaPlayer();
private static bool isPlaying = false;
public Clicker(KeyInfo k)
{
player.Open(new Uri(@"C:\Users\chris\Downloads\Recording2.wav"));
player.MediaEnded = Loop;
}
private void StartSoundClicker()
{
player.Play();
isPlaying = true;
}
private static void Loop(object? sender, EventArgs? e)
{
Application.Current.MainWindow.Dispatcher.Invoke(() =>
{
if (isPlaying)
player.Play();
});
}
private async void StopSoundClicker()
{
await Application.Current.MainWindow.Dispatcher.Invoke(async () =>
{
await Task.Delay(70);
player.Stop();
isPlaying = false;
});
}
CodePudding user response:
The error occurs when you're calling .Dispatcher
on MainWindow instnace from background thread.
Replace
Application.Current.MainWindow.Dispatcher
With
Application.Current.Dispatcher
I think this variant is what StopSoundClicker
should be!
private async Task StopSoundClicker()
{
await Task.Delay(70);
Application.Current.Dispatcher.Invoke(() =>
{
player.Stop();
isPlaying = false;
});
}
CodePudding user response:
In general, you should use the Dispatcher
of the element you are accessing.
Of course, this will almost always be Application.Current.Dispatcher
.
But in some cases this may not be the case.
And in CodeBehind, you can simply use Dispatcher
- this is a property of the Window. And all its elements have the same Dispatcher
.
But in your task, I don't see the need to use it at all - Clickers are always called on the UI thread.
In my opinion, this code should work:
private async void StopSoundClickerAsync(object sender, RoutedEventArgs e)
{
await Task.Delay(70);
player.Stop();
isPlaying = false;
}