尝试在C#类中播放声音时出现WPF错误“调用线程无法访问此对象”

ztmd8pv5  于 2022-11-18  发布在  C#
关注(0)|答案(2)|浏览(195)

在我的classClicker.cs中,我尝试使用MediaPlayer播放声音。但是,每当我调用该方法来关闭MediaPlayer时,我都会收到错误消息,即调用线程无法访问此对象,因为另一个线程拥有它。此代码在MainWindow.xaml.cs中工作正常,但在Clicker.cs中不工作。我在网上发现了类似的问题,修复方法是使用Dispatcher.Invoke()。但是,这不起作用。错误特别发生在调用StopSoundClicker()时。我的代码如下:

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;
    });
}
hfsqlsce

hfsqlsce1#

通常,您应该使用正在访问的元素的Dispatcher
当然,这几乎总是Application.Current.Dispatcher
但在某些情况下,情况可能并非如此。
在CodeBehind中,你可以简单地使用Dispatcher--这是Window的一个属性,它的所有元素都有相同的Dispatcher
但是在您的任务中,我根本不认为需要使用它- Clickers总是在UI线程上调用的。
在我看来,这段代码应该可以工作:

private async void StopSoundClickerAsync(object sender, RoutedEventArgs e)
{
   await Task.Delay(70);

   player.Stop();
   isPlaying = false;
}
oymdgrw7

oymdgrw72#

当您从后台线程调用MainWindow示例上的.Dispatcher时,会发生此错误。
替换

Application.Current.MainWindow.Dispatcher

Application.Current.Dispatcher

我认为这个变体就是StopSoundClicker应该是的!

private async Task StopSoundClicker()
{
    await Task.Delay(70);
    Application.Current.Dispatcher.Invoke(() =>
    {
        player.Stop();
        isPlaying = false;
    });
}

相关问题