2013-05-21 5 views
0

기본적으로, 내 양식에 여러 개의 단추가 있고 단추 스톱워치를 보여주고 싶습니다. 단추를 눌렀을 때의 텍스트. (버튼은 토글 버튼으로 수정됩니다.) 버튼이 꺼지면 타이머를 중지하고 재설정 할 수 있습니다. 간단하지만 충분히 보였습니다. 그러나 어떤 순서로 누를 수있는 버튼이 여러 개 있고 스레딩에 대해 전혀 알지 못하기 때문에 이것은 제가 생각했던 것보다 훨씬 어려워 보입니다. 때, 난 너무 스레딩을 모르는스톱워치 C에서 버튼 텍스트 변경 #

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); 
     } 
    } 

문제는 다음과 같습니다

내 망하는 의도는 지속적으로 매 초마다 실행 버튼이 코드를 사용하여 누를 경우에만 interager을 interates 기능을 가지고 있었다 그 기능을 호출,이 일을하고 붙어.

어느 쪽이든, 일단 이것을 호출하면 button [button]을 포함하여 모든 버튼을 업데이트하는 업데이트 기능이 호출됩니다. [0]; (버튼 주위에 배열 된 배열)

너무 많은 CPU 사용 및/또는 단순히 작동을 일으키지 않는 더 나은 방법인가요?

모든 도움에 감사드립니다! - 존 아이비

+0

나는 당신이 무엇을하려고하는지 잘 이해하지 못합니다. 하나 또는 여러 개의 타이머가 있습니까? 어떤 버튼이나 특정 버튼에서 클릭이 발생하면 스톱워치를 시작/중지하고 싶습니까? – MAV

+0

UI가 멈추는 주 스레드를 잠자고 있습니다. –

+0

나는 각각의 타이머를 제어하는 ​​여러 개의 단추가 있습니다. 그리고 각각의 타이머의 시작과 멈춤은 버튼 자체에 의해 제어됩니다. 따라서 button1이 켜지면 타이머가 시작되고 button1.Text에 표시됩니다. 버튼 1이 꺼지면 멈 춥니 다. 다른 사람과 동시에이 작업을 수행 할 수 있어야합니다. 따라서 button1과 button5는 자신의 타이머를 작동시킬 수 있습니다. 알다? –

답변

0

Application.DoEvents() 루프 내부에 넣으십시오. . 하지만 threading을 기울이기 시작하는 것이 좋습니다. 당신은 방금 스레드를 시작하는 방법과 십자가 안전 전화를 만드는 방법을 배울 것입니다 다음 간단하게 backgroundworker을 사용하는 것입니다. 이보세요 http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

여기 스레드 솔루션도 원하는대로입니다. 테스트도. 정지 변수로 Tag를 사용했습니다. 하지만 버튼을 상속하여 상태 버튼을 만들 수 있습니다. 더 명확한 방법이 될 것입니다. 아래 코드는 버튼 당 하나의 스레드를 사용합니다. 그래서 더 나은 솔루션을 만들기 위해 한 스레드에서 만들어야합니다.. 이 코드를 수정하여 하나의 스레드에서 모든 검사를 수행 할 수 있습니다. 이를 위해 일단 스레드를 시작하면 각 버튼에 dinamically count 함수를 첨부하기위한 델리게이트를 만들거나 이전에 버튼을 전달할 수 있습니다. 한 단어로 여러 가지 방법이 있습니다. 행운을 빌어 요 당신은 = 성상이 CheckedChanged에 대한 이벤트 처리기에서 속성 버튼과 체크 박스를 사용하여 가정

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; 

     } 

    } 
+0

Application.DoEvents()가 도움이되는 방법에 대해 혼란 스럽습니까? –

+0

@JohnIvey 당신의 루프 안에서 – qwr

+0

나는 while (true) 문 안에 넣고, 여전히 '멈 춥니 다'. : \ –

0

: 당신은 또한 몇 가지 간단한 필요

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(); 
} 

:

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; 
     } 
    } 
} 
이 조깅 기능을 변경

체크 박스와 현재 시간을 저장할 클래스 :

class CheckboxCounter 
{ 
    public CheckBox CheckBox; 

    public int Time; 
} 

그러면 여러 개의 체크 박스를 추가하고 CheckedChanged 이벤트를 CheckBoxCheckedChanged에 설정할 수 있습니다.

+0

정말 시간의 문자열을 버튼에 넣고 싶습니다. (예 : Button1.Text) 아니면 코드를 잘못 이해 했습니까? –

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(); 
    } 

}