我有一节课,播放这样的音乐.它还在构造期间将GUI线程id保存在私有int中:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
是否可以调用FireOnTrackComplete()具有特定ID的线程.在这种情况下,ID存储在this.GuiThreadId?
我遇到的大多数解决方案都建议我在监听OnTrackComplete事件处理程序的方法中使用GUI代码中的调用.我想避免这样做.我想在MediaPlayer课堂上做所有事情
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);
}
}
Run Code Online (Sandbox Code Playgroud)
该的SynchronizationContext类是为了解决这个问题.在构造函数中复制其Current属性的值,稍后使用其Post()或Send()方法.这可确保您的库可以与任何GUI类库一起使用.像这样:
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;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
698 次 |
| 最近记录: |