我有一个改变字段的线程
private void SongChange(object sender, RoutedEventArgs e)
{
SongChangeAction();
songLength = (int)BGMPlayer.NaturalDuration.TimeSpan.TotalSeconds;
songProgress = new Thread(SongProgressUpdate) { IsBackground = true };
songProgress.Start();
}
private void SongProgressUpdate()
{
while (true)
{
Dispatcher.Invoke(() => { workingResources.SongProgress = BGMPlayer.Position.TotalSeconds / songLength * 100; });
Thread.Sleep(1000);
}
}
注意:songLength
是double
,BGMPlayer
是MediaElement
在后台播放音乐,workingResources.SongProgress
是double
绑定到一个Progress Bar
当我使用" X"关闭程序时按钮或在任务栏上,程序抛出异常System.Threading.Tasks.TaskCanceledException
即使我尝试设置线程IsBackground = true
但它不会抛出异常如果我使用Visual Studio停止程序。
行中的程序抛出异常:
Dispatcher.Invoke(() => { workingResources.SongProgress = BGMPlayer.Position.TotalSeconds / songLength * 100; });
我可以通过使用try / catch来阻止它,但我想找到更高效的东西
答案 0 :(得分:1)
尝试使用Microsoft的Reactive Framework。然后你可以这样做:
private void SongChange(object sender, RoutedEventArgs e)
{
SongChangeAction();
songLength = (int)BGMPlayer.NaturalDuration.TimeSpan.TotalSeconds;
IDisposable subscription =
Observable
.Interval(TimeSpan.FromSeconds(1.0))
.ObserveOnDispatcher()
.Subscribe(x => workingResources.SongProgress = BGMPlayer.Position.TotalSeconds / songLength * 100);
}
您只需要确保在关闭应用时保存对subscription
的引用并在其上调用.Dispose()
。
NuGet“System.Reactive”和“System.Reactive.Windows.Threading”,并将using System.Reactive.Linq;
添加到您的代码中。
答案 1 :(得分:1)
尝试在窗口关闭时使用CancellationToken
:
private readonly CancellationTokenSource _shutDown = new CancellationTokenSource();
public WindowName()
{
this.Closed =+ (s, e) => this._shutDown.Cancel();
}
private void SongChange(object sender, RoutedEventArgs e)
{
SongChangeAction();
songLength = (int)BGMPlayer.NaturalDuration.TimeSpan.TotalSeconds;
songProgress = Task.Factory.StartNew(SongProgressUpdate, this._shutDown.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
private void SongProgressUpdate()
{
while (!this._shutDown.IsCancellationRequested)
{
Dispatcher.Invoke(() => { workingResources.SongProgress = BGMPlayer.Position.TotalSeconds / songLength * 100; });
Thread.Sleep(1000);
}
}