C# WPF-在循环中更新UI时播放声音
我是WPF的新手,我最终通过更新UI创建了一个for循环。但我搜索了很多网站,没有找到解决问题的方法: 在我的主窗口中,我有一个标签C# WPF-在循环中更新UI时播放声音,c#,wpf,multithreading,audio,data-binding,C#,Wpf,Multithreading,Audio,Data Binding,我是WPF的新手,我最终通过更新UI创建了一个for循环。但我搜索了很多网站,没有找到解决问题的方法: 在我的主窗口中,我有一个标签 <Label x:Name="labelName" Content="{Binding LabelNameContent}"/> 标签的文本在循环中得到更新,循环过程中应播放声音 Task.Factory.StartNew(() => { sound.Play(); for(int i=0; i< 150; i++)
<Label x:Name="labelName" Content="{Binding LabelNameContent}"/>
标签的文本在循环中得到更新,循环过程中应播放声音
Task.Factory.StartNew(() =>
{
sound.Play();
for(int i=0; i< 150; i++)
{
LabelNameContent = i.ToString();
Thread.Sleep(500);
}
});
Task.Factory.StartNew(()=>
{
声音。播放();
对于(int i=0;i<150;i++)
{
LabelNameContent=i.ToString();
睡眠(500);
}
});
我的问题是,声音被打断了,而且一直在结巴
如何更新用户界面并播放声音?您使用什么课程播放声音?根据类的不同,可能存在一个事件,您可以向其注册处理程序,以便在声音播放结束时收到通知。因此,您可以调用
声音。播放
,等待自动恢复事件
,然后在收到声音结束的通知时设置
自动恢复事件。最后,您的循环可以继续。大概是这样的:
在您表格中的班级级别:
AutoResetEvent soundFinishedFlag = new AutoResetEvent(false);
然后,在创建声音播放器的地方,您将执行以下操作:
sound.Finished += SoundFinished;
请注意,上面这一行完全取决于您使用的声音播放器!这只是一个例子
最后,您的匿名函数变成:
Task.Factory.StartNew(() =>
{
sound.Play();
// Wait for the sound to finish playing!
AutoResetEvent.WaitOne(); // Note that this can take an optional time out so you can limit how long your program waits, if you want to.
for(int i = 0; i < 150; i++)
{
LabelNameContent = i.ToString();
Thread.Sleep(500);
}
});
Task.Factory.StartNew(()=>
{
声音。播放();
//等待声音结束播放!
AutoResetEvent.WaitOne();//请注意,这可能需要一个可选的超时时间,以便您可以限制程序等待的时间(如果需要)。
对于(int i=0;i<150;i++)
{
LabelNameContent=i.ToString();
睡眠(500);
}
});
当然,如果您使用的声音播放器没有提供“我完成了”的事件通知,这是没有帮助的
编辑
根据您在评论中的回复,您需要让SoundPlayer
在与UI和更新标签内容的UI分开的线程中播放其声音
我的WPF应用程序使用SoundPlayer
播放几种不同声音中的一种。每个声音都有自己专用的SoundPlayer
实例。当我播放声音时,会启动一个新的线程
&对该线程
调用播放
方法。这有以下优点:
SoundPlayer
的线程即可嗯,循环的每次迭代都睡半秒钟是没有用的。使用
Task.Delay
而不是Thread.Sleep
。使用Task.Delay
用户界面不再更新:/谢谢,但我不想等到声音结束,我希望它在循环运行时播放。另外,我用的是SoundPlayer。谢谢!不知道为什么我没有看到这个简单的解决方案^^Works=)
Task.Factory.StartNew(() =>
{
sound.Play();
// Wait for the sound to finish playing!
AutoResetEvent.WaitOne(); // Note that this can take an optional time out so you can limit how long your program waits, if you want to.
for(int i = 0; i < 150; i++)
{
LabelNameContent = i.ToString();
Thread.Sleep(500);
}
});