如何允许按钮停止操作并使该操作影响表单控件

本文关键字:操作 影响 表单 控件 按钮 何允许 | 更新日期: 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,对于实时音乐来说,情况可能就是这样。