0

基本上,我的表单中有多个按钮,我希望它在按钮中显示一个秒表。按下按钮时的文本。(按钮被修改为切换按钮。)并在按钮关闭时停止和重置计时器。看起来很简单,但是因为我有多个可以按任何顺序按下的按钮,而且我对线程一无所知,所以这似乎比我想象的要困难得多。

我最初的意图是拥有一个每秒不断运行的函数,并且只有在使用以下代码按下按钮时才与 interager 交互:

public void Jogger()//purpose is to step up time[0] every second only when a button is on.
    {
        while (true)
        {
            for (int i = 0; i < 16; i++)
            {
                if (btnstat[i])
                    time[i]++;
            }
            Thread.Sleep(1000);
        }
    }

问题是,我不知道线程,所以当我调用函数时,它会卡住这样做,只有这个。

无论哪种方式,一旦调用它,我所做的就是调用我的更新函数来更新所有按钮,包括显示时间 [0] 的 button.Text;(围绕按钮构建的阵列)

他们这样做是不是一种更好的方法,不会导致过多的 CPU 使用和/或简单地工作?

感谢所有的帮助!——约翰·艾维

4

3 回答 3

0

Application.DoEvents()为简单起见,放在循环内。. 但建议开始瘦身threading。您将学习如何启动线程以及如何进行跨线程安全调用下一个简单的将是使用backgroundworker。看看这个http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

好的,这里也是您想要的线程解决方案。也测试过了。作为停止变量,我使用了 Tag。但是你可以继承按钮来制作状态按钮。它是更清晰的方式。下面的代码将每个按钮使用一个线程。因此,您应该将其放在一个线程中以使其成为更好的解决方案。您可以修改此代码以在一个线程内进行所有检查。为此,您启动线程一次可以使委托为每个按钮附加动态计数功能,或者您可以在之前传递按钮。一句话,有不止一种方法可以做到。祝你好运

this.button1.Click += new System.EventHandler(this.button_Click);
this.button2.Click += new System.EventHandler(this.button_Click);
...and so on
  private void button_Click(object sender, EventArgs e)
        {
           Thread x= new Thread(new ParameterizedThreadStart(Jogger2));
            x.Start(sender);

        }


        private void button_Click(object sender, EventArgs e)
    {
        Button mybtn=sender as Button;
        if((string)mybtn.Tag=="start"){
            mybtn.Tag ="";
            return;
         }
        mybtn.Tag = "start";
       Thread x= new Thread(new ParameterizedThreadStart(Jogger2));
        x.Start(sender);

    }


    private bool  setResult(object obj,string text)
    { 
        if (this.textBox1.InvokeRequired)
        {
            Func<Button,string, bool > d = new Func<Button,string,bool >(setResult);
            return (bool)this.Invoke(d,obj,text);

        }
        else
        {
            Button btn=obj  as Button;

            if (btn != null)
            {
                btn.Text = text;
                if ((string)btn.Tag !="start") return false;
            }
            return true;
        }
    }
    private void Jogger2(object mybtn)
    {
        int ii = 0; 
        while (true)
        {
            Thread.Sleep(1000);
                //replace with your code
                ii += 1;
                if (!setResult(mybtn, ii.ToString())) break; 

        }

    }
于 2013-05-21T18:47:18.877 回答
0

假设您在 CheckedChanged 的​​事件处理程序中使用具有属性 Button = Appearence 的复选框:

private void CheckBoxCheckedChanged(object sender, EventArgs e)
{
    CheckBox checkBox = (CheckBox) sender;

    if (checkBox.Checked)
    {
        Timer timer = new Timer {Interval = 1000};
        timer.Tick += Jogger;
        timer.Start();
        timer.Tag = new CheckboxCounter {CheckBox = checkBox, Time = 0};
        checkBox.Tag = timer;
    }
    else
    {
        Timer timer = checkBox.Tag as Timer;
        if (timer != null)
        {
            timer.Tag = null;
            timer.Stop();
            timer.Dispose();
            checkBox.Tag = null;
        }
    }
}

改变你的慢跑功能:

private void Jogger(object a_sender, EventArgs a_eventArgs)
{
    Timer timer = (Timer) a_sender;
    CheckboxCounter data = (CheckboxCounter)timer.Tag;
    data.Time++;
    data.CheckBox.Text = data.Time.ToString();
}

您还需要一些简单的类来存储复选框和当前时间:

class CheckboxCounter
{
    public CheckBox CheckBox;

    public int Time;
}

然后您可以添加任意数量的复选框并将事件 CheckedChanged 设置为 CheckBoxCheckedChanged。

于 2013-05-21T18:54:52.653 回答
0

试试这个。重新构建或运行后,您的工具箱顶部应该有新的“ButtonTimer”。将一对放在您的表单上,运行它,然后查看单击它们时会发生什么。右键单击它们以“重置”它们:

public class ButtonTimer : CheckBox
{

    private System.Windows.Forms.Timer Tmr = new System.Windows.Forms.Timer();
    private System.Diagnostics.Stopwatch SW = new System.Diagnostics.Stopwatch();

    public ButtonTimer()
    {
        this.Tmr.Interval = 500;
        this.Tmr.Tick += new EventHandler(tmr_Tick);
        this.Appearance = System.Windows.Forms.Appearance.Button;
        this.CheckedChanged += new EventHandler(ButtonTimer_CheckedChanged);

        ContextMenuStrip cms = new ContextMenuStrip();
        ToolStripItem tsi = cms.Items.Add("Reset");
        tsi.Click += new EventHandler(tsi_Click);
        this.ContextMenuStrip = cms;
    }

    protected override void OnLayout(LayoutEventArgs levent)
    {
        base.OnLayout(levent);
        this.Text = TimeSpan.Zero.ToString(@"hh\:mm\:ss");
    }

    private void ButtonTimer_CheckedChanged(object sender, EventArgs e)
    {
        if (this.Checked)
        {
            this.SW.Start();
            this.Tmr.Start();
        }
        else
        {
            this.SW.Stop();
            this.Tmr.Stop();
        }
    }

    private void tmr_Tick(object sender, EventArgs e)
    {
        this.UpdateTime();
    }

    private void UpdateTime()
    {
        this.Text = this.SW.Elapsed.ToString(@"hh\:mm\:ss");
    }

    private void tsi_Click(object sender, EventArgs e)
    {
        if (this.SW.IsRunning)
        {
            SW.Restart();
        }
        else
        {
            SW.Reset();
        }
        this.UpdateTime();
    }

}
于 2013-05-21T20:21:04.547 回答