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]; (ボタンの周りに構築された配列)

CPUの使用量がそれほど多くない、および/または単に機能する、これを行うためのより良い方法はありますか?

助けてくれてありがとう!-ジョン・アイビー

4

3 に答える 3

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 に答える
0

Application.DoEvents()簡単にするために loop の中に入れます。. しかし、傾き始めることをお勧めしthreadingます。スレッドを開始する方法と、クロススレッドセーフコールを作成する方法を学習するだけです。次に簡単なのは、backgroundworker. これを見てください http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

わかりました、これもあなたが望むようにスレッドソリューションです。あまりにもテスト。ストップ変数としてタグを使用しました。ただし、ボタンを継承して状態ボタンを作成できます。より明確な方法になります。以下のコードでは、ボタンごとに 1 つのスレッドを使用します。したがって、より良い解決策にするために、1つのスレッドで作成する必要があります。このコードを変更して、1 つのスレッド内ですべてのチェックを行うことができます。このために、スレッドを一度開始すると、ボタンごとに動的にカウント関数をアタッチするデリゲートを作成したり、ボタンを前に渡すことができます。1 つの言葉で、それを行う方法は複数あります。幸運を

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 に答える