what I'm trying to do:
I use a WebApiApplication to control a music player on a server (imagine it as a kind of democratic music player: my housemates and me all have access to it via smartphone and can control it in the same way).
Web calls are made like this:
http://localhost:64199/api/Music?category=Ambient&action=play
or
http://localhost:64199/api/Music?category=Ambient&action=next
My controller looks like this:
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");
}
}
The Player is a specialised System.Windows.Media.MediaPlayer and implemented as a Singleton. It ist first instantiated in the Global.asax to start with a random song.
Whenever I try to access it afterwards (via web call), the application crashes with an InvalidOperationException, because it cannot access the thread the player is running at.
I have figured out what happens with the Threads:
As you see, I have an idea of what the problem is, but as I'm pretty new to .NET, I just don't know how to solve it. I need something like a global unique controller which controlls the player and is called by those ApiControllers.
I hope this question has not been asked before, I tried to look it up but I didn't exactly know what to search for.
The MediaPlayer is inherited from a DispatcherObject and it states:
Only the thread that the Dispatcher was created on may access the DispatcherObject directly. To access a DispatcherObject from a thread other than the thread the DispatcherObject was created on, call Invoke or BeginInvoke on the Dispatcher the DispatcherObject is associated with.
Now I don't have a setup available to test this and I don't think that MediaPlayer class was designed for use in a Web Application, but you might try this:
dmp.Dispatcher.Invoke(() => dmp.PlayNext(); );
It will invoke the PlayNext
method on the correct thread. If that doesn't result in success I'm afraid you have to accept it will not work.