如何允许按钮停止操作并使该操作影响表单控件
本文关键字:操作 影响 表单 控件 按钮 何允许 | 更新日期: 2023-09-27 18:24:07
因此,基本上,我正在创建音乐软件,并希望能够在必要时暂停/停止歌曲。然而,当歌曲播放时,它不允许使用表单上的任何控件,"KeyDown"事件似乎也不受影响,因此我无法停止歌曲,直到它结束。
我曾尝试使用"thread"类的实例来实现这一点,但问题是我需要在表单上使用某些"Label"控件,而从另一个线程似乎很难做到这一点。
以下是我"玩"代码的要点。
Sound[] notes = song.Sounds;
double seconds = 0;
foreach (Sound sound in notes)
{
seconds += (double)sound.NoteType.GetDuration(tempo) / 1000;
}
timeleft = seconds;
lblSecondsLeft.Text = timeleft + "";
double length = notes.Length;
double thing = (100 / length);
double otherthing = Math.Round(thing);
sounds = notes;
double progress = 0;
for (int i = 0; i < notes.Length; i++)
{
Sound sound = notes[i];
lblTempo.Text = tempo.ToString();
string note = sound.Note.ToString();
lblNote.Text = note;
progress += thing;
lblProgress.Text = progress + "%";
seconds -= (double)sound.NoteType.GetDuration(tempo) / 1000;
lblSecondsLeft.Text = seconds + " seconds left";
sound.PlaySound(song.Channel);
}
这是一种烦恼,但这是众所周知的烦恼。您必须在一个单独的(非UI)线程上运行非UI代码,以便UI对按钮和文本更新等保持响应。但是,这意味着您必须通过在更新期间切换到UI线程来从非UI线程更新UI。以下代码执行此操作。
注意1:这是从我手头的一些代码中修剪出来的,所以没有正确检查。
注2:这是一个WPF版本,WinForms略有不同,但原理相同。
public String LabelText{
get {
if (!this.Dispatcher.CheckAccess()) {
return (String)this.Dispatcher.Invoke(new Func<String>(() => { return LabelText; }));
}
return Label.Text;
}
set {
if (!this.Dispatcher.CheckAccess()) {
this.Dispatcher.Invoke(new Action(() => { LabelText = value; }));
return;
}
LabelText = value;
}
}
这是通过检查get/set是否在正确的线程上进行的,如果不是,则切换线程并调用自己(现在在正确的螺纹上),完成get/set并返回。如果不需要线程等待屏幕更新,也可以使用BeginInvoke,对于实时音乐来说,情况可能就是这样。