访问全局对象时出现.NET Web Api InvalidOperationException

本文关键字:NET Web Api InvalidOperationException 全局 对象 访问 | 更新日期: 2023-09-27 18:01:02

我要做的事情:

我使用WebApiApplication来控制服务器上的音乐播放器(把它想象成一种民主的音乐播放器:我和我的室友都可以通过智能手机访问它,并且可以用同样的方式控制它(。

网络呼叫是这样进行的:

http://localhost:64199/api/Music?category=Ambient&action=播放

http://localhost:64199/api/Music?category=Ambient&动作=下一个

我的控制器看起来像这样:

public class MusicController : ApiController
{
    const string MUSICPATH = @"...'Songs";
    public HttpResponseMessage Get(string category, string action, string song = "", bool shuffle = false)
    {
        // DirMusicPlayer.Category = category;
        DirMediaPlayer dmp = DirMediaPlayer.getInstance(category);
        System.Diagnostics.Debug.WriteLine("Thread-ID (Ctrl): " + Thread.CurrentThread.ManagedThreadId);
        switch (action)
        {
            case "play":
                if (song.Equals(""))
                {
                    dmp.PlayAll();
                }
                else
                {
                    dmp.PlaySong(song);
                }
                break;
            case "stop":
                dmp.Stop();
                break;
            case "next":
                dmp.PlayNext();
                break;
            case "prev":
                dmp.PlayPrevious();
                break;
            case "shuffle":
                dmp.Shuffle = shuffle;
                break;
            default:
                break;
        }

        return Request.CreateResponse(HttpStatusCode.OK, "Playing");
    }
}

播放器是一个专门的System.Windows.Media.MediaPlayer,并作为一个Singleton实现。它首先在Global.asax中实例化,从一首随机歌曲开始。

每当我稍后尝试访问它(通过web调用(时,应用程序都会崩溃,并出现InvalidOperationException,因为它无法访问播放器运行的线程。

我已经弄清楚线程会发生什么:

  1. 线程ID(AppStart(:1//Global.asax-Thread
  2. 线程ID(MediaPlayer(:1
  3. 线程ID(MusicController(:7//线程池中的控制器实例
  4. 线程ID(MediaPlayer(:7//崩溃,因为Media Player实例属于线程1

正如你所看到的,我知道问题是什么,但由于我对.NET还很陌生,我不知道如何解决它。我需要一个全局唯一控制器来控制播放器,并由那些ApiControllers调用。

我希望这个问题以前没有人问过,我试着查了一下,但我不知道该找什么。

访问全局对象时出现.NET Web Api InvalidOperationException

MediaPlayer是从DispatcherObject继承的,它声明:

只有在其上创建Dispatcher的线程才能直接访问DispatcherObject。要从创建DispatcherObject的线程以外的线程访问Dispatcher对象,请在与DispatcherObject关联的Dispatcher上调用Invoke或BeginInvoke。

现在我没有可用的设置来测试这一点,我不认为MediaPlayer类是为在Web应用程序中使用而设计的,但你可以尝试一下:

 dmp.Dispatcher.Invoke(() => dmp.PlayNext(); );

它将在正确的线程上调用PlayNext方法。如果这不能带来成功,恐怕你必须接受这是行不通的。