基本上,我的表单中有多个按钮,我希望它在按钮中显示一个秒表。按下按钮时的文本。 (按钮被修改为切换按钮。)并在按钮关闭时停止并重置音调。看起来很简单,但因为我有多个按钮可以按任意顺序按下,而且我对线程没有任何了解,这似乎比我想象的要困难得多。
我的原始意图是拥有一个每秒不断运行的功能,并且只有在使用此代码按下按钮时才会对交互者进行交互:
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);
}
}
问题是,我不知道线程,所以当我调用该函数时,它只是这样做了。
无论哪种方式,一旦调用它,我所做的就是调用我的更新函数来更新所有按钮,包括button.Text,它显示时间[0]; (围绕按钮构建的数组)
他们是一个更好的方法,这不会导致如此多的CPU使用和/或只是工作?
感谢您的帮助! -John Ivey
答案 0 :(得分:0)
Application.DoEvents()
为简单起见放在循环中。 。但建议开始倾斜threading
。您将学习如何启动线程以及如何使跨线程安全调用
接下来的简单就是使用backgroundworker
。看这个http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
ok这里也是你想要的线程解决方案。测试过了。作为一个停止变量我用Tag。但你可以继承按钮来制作状态按钮。这是更清晰的方式。 以下代码将使用每个按钮一个线程。所以你应该在一个线程中使它成为更好的解决方案。您可以修改此代码以在一个线程内执行所有检查。为此你启动线程一旦可以为每个按钮附加dinamically计数功能委托,或者你可以之前传递按钮。用一个词来说,有不止一种方法可以做到这一点。祝你好运
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;
}
}
答案 1 :(得分:0)
假设您使用带有属性Button = Appearence的复选框,在CheckedChanged的事件处理程序中:
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。
答案 2 :(得分:0)
试一试。重新构建或运行后,您应该在ToolBox顶部使用新的“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();
}
}