I have a class which plays some music like this. It also saves the GUI thread id in a private int during construction:
public class MediaPlayer {
public event EventHandler<Track> OnTrackComplete;
private int GuiThreadId;
public MediaPlayer(...){
...
this.GuiThreadId = Thread.CurrentThread.ManagedThreadId;
}
public void Play(){
Task t = Task.Factory.StartNew(() =>
{
//On Song complete
FireOnTrackComplete();
});
}
protected virtual void FireOnTrackComplete()
{
if (OnTrackComplete != null)
OnTrackComplete(this, loadedTrack);
}
}
Is it possible to call FireOnTrackComplete() on a Thread with a specific ID. In this case, the ID is stored in the this.GuiThreadId?
Most of the solutions I have come across suggest I use invokes in my GUI code in methods which listen to the OnTrackComplete event handler. I want to avoid doing this. I want to do everything in the MediaPlayer class
public class MediaPlayer {
public event EventHandler<Track> OnTrackComplete;
private SynchronizationContext callerCtx;
public MediaPlayer(...){
...
callerCtx = System.Threading.SynchronizationContext.Current;
}
public void Play(){
Task t = Task.Factory.StartNew(() =>
{
//On Song complete
FireOnTrackComplete();
});
}
protected virtual void FireOnTrackComplete()
{
Action e = () =>
{
if (OnTrackComplete != null)
OnTrackComplete(this, loadedTrack);
};
FireEvent(e);
}
//... Other events ... //
protected virtual void FireEvent(Action e)
{
if (callerCtx == null)
e();
else
callerCtx.Post(new SendOrPostCallback((_) => e()), null);
}
}
The SynchronizationContext class was meant to solve this problem. Copy the value of its Current property in the constructor, use its Post() or Send() method later. This ensures your library will work with any GUI class library. Like this:
class MediaPlayer {
public MediaPlayer() {
callersCtx = System.Threading.SynchronizationContext.Current;
//...
}
private void FireOnTrackComplete() {
if (callersCtx == null) FireOnTrackCompleteImpl();
else callersCtx.Post(new System.Threading.SendOrPostCallback((_) => FireOnTrackCompleteImpl()), null);
}
protected virtual void FireOnTrackCompleteImpl() {
var handler = OnTrackComplete;
if (handler != null) handler(this, loadedTrack);
}
private System.Threading.SynchronizationContext callersCtx;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With