2013-01-23 22 views
1

나는 "Worker"객체가 여러 개 있고 일정 시간이 소요되는 작업을 수행하는 프로그램을 작성하고 있습니다. 잘 작동하는 내부 타이머가있는 작업자 클래스를 만들었습니다. 그러나 "작업"을 수행 할 때마다 화면 새로 고침을 위해 몇 초 동안 기다려야합니다 (각 작업자가 원격 화면에서 데이터를 스크래핑하고 자동화를 수행함).타이머를 중단하지 않고 프로그램을 일시 중지 C#

내가 잠깐 이해할 수 있기 때문에 잠을 자고 싶지 않다. 다른 작업자 개체에서 타이머를 일시 중지한다. (내 응용 프로그램은 솔직히 말해서, 나는 솔직하게 나는 브랜드 다. C#에 익숙하지 않고 과도하게 사용하고 싶지 않았습니다.) 거기에 실제로 스레드 전체를 걸지 않는 사용할 수있는 또 다른 대기 함수가 있습니까?

몇 가지 추가 정보 :

  • 는 지금이 콘솔 응용 프로그램입니다,하지만 노동자 구현
  • 내 타이머를하고있는 내가 어떻게 결국에 사용자에게 피드백을 제공하기 위해 UI 양식을 구축한다) 데스크탑 (그래서 C 번호의 어떤 버전/위해 MS VS 익스프레스 2012을 사용하여
  • , System.Timers를 사용하고 아주 잘 작동
  • 나는 C# 프로그래밍에 대한 새로운 생각되는 것은,이 너무 작은 단어를 사용하십시오, 내 첫 번째 프로젝트입니다 . NET입니다!)

아래의 코드 (실제 작업은 "startWorking"메서드를 사용하여 수행되지만 아무 것도 구현되지 않습니다.) 이것은 타이머가 작동하는 판매 된 빌드입니다. 또한 주 타이머는 현재 여러 타이머를 테스트하는 용도로만 사용되고 있습니다)

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Timers; 

namespace Multi_Timers 
{ 
//worker class that includes a timer 
public class Worker 
{ 
    private Timer taskTimer; 
    private bool available = true; 
    private string workerName; 
    private string startWork; 
    private int workTime; 

    // properties 
    public bool isAvailable { get { return this.available; } } 
    public string name { get { return this.workerName; } } 

    // constructor 
    public Worker(string name) 
    { 
     this.workerName = name; 
     Console.WriteLine("{0} is initialized", name); 
    } 

    // start work timer 
    public void startWorking(int duration) { 

     if (this.available == true) 
     { 
      this.available = false; 
      this.taskTimer = new Timer(); 
      this.taskTimer.Interval = duration; 
      this.taskTimer.Elapsed += new ElapsedEventHandler(doneWorking); 
      this.taskTimer.Enabled = true; 
      this.startWork = DateTime.Now.ToString(); 
      this.workTime = duration/1000; 
     } 
     else Console.WriteLine("Sorry, {0} was not available to work", this.workerName); 
    } 

    // Handler for timer 
    public void doneWorking(object sender, ElapsedEventArgs e) 
    { 
     Console.WriteLine("{0}: {1}/{2} min/{3}", this.workerName, this.startWork, this.workTime/60, e.SignalTime.ToLocalTime()); 
     this.taskTimer.Enabled = false; 

     this.available = true; 

    } 
} 

//main program 
class Program 
{ 
    static void Main(string[] args) 
    { 
     Random r = new Random(); 

     // initialize worker(s) 
     Worker bob = new Worker("Bob"); 
     Worker bill = new Worker("Bill"); 
     Worker jim = new Worker("Jim"); 

     // q to exit 
     while (true) 
     { 
      if (bob.isAvailable) { 

       bob.startWorking(r.Next(1 * 60, 150 * 60) * 1000); 
      } 
      if (bill.isAvailable) 
      { 
       bill.startWorking(r.Next(1 * 60, 150 * 60) * 1000); 
      } 
      if (jim.isAvailable) 
      { 
       jim.startWorking(r.Next(1 * 60, 150 * 60) * 1000); 
      } 

     } 
    } 
} 
} 

사전에 도움을 주셔서 감사합니다! 이 커뮤니티의 사례를 읽으면서 C#을 조금 배우기 시작하는 것이 중요했습니다.

답변

2

내가 그것을 이해하는도 다른 노동자에 타이머를 일시 중지하기 때문에 개체, 스레드을 자고 싶어하지 않는 잘못된

; 그것은 타이머를 멈추지 않을 것이다.

내 응용 프로그램은 실제로는 그렇지 않아, 단일 스레드

없음입니다. 타이머는 다른 스레드를 만들고 사용하여 동작을 구현합니다. Elapsed 이벤트 처리기는 스레드 풀 스레드에서 시작됩니다. 코드와


하나의 주요 문제는 main 방법은 세 가지 객체에 "busywait"그들이 수행하는 경우 그들에게 물어 지속적으로 폴링을하고 있다는 것입니다. 이것은 비싸다. 기본적으로 당신은 아이들이 "우리는 아직 거기 있습니까?"라고 묻는 것과 같습니다. 1 초에 몇 백 번. 네가 끝냈다 고 말할 때까지 기다리는 것이 더 좋을 것 같지 않은가! (가능하고 좋은 옵션입니다.)

이 경우 간단한 해결책 중 하나는 Main이 아니라 작업자의 루프를 수행하는 것입니다. startWorking의 구현을 while 루프로 감싸고 메인 코드를 영원히 기다려야합니다 (예 : Thread.Sleep(Timeout.Infinite);).보다 복잡한 옵션은 작업자가 Task, 이벤트 또는 차단 대기 ("조인"이라고도 함) 메소드를 제공하여 완료 시점을 나타낼 수 있습니다.

고려중인 옵션, 그 Main 것이다 도움에 조금의 Thread.Sleep을 추가하지만, 단지 당신이 덜 자주, 그들을 가진보다는 거기에 기다리고있을 때 물어 당신의 아이를 말하고의 네가 거기있을 때 너 한테 말해 줄거야.

+0

덕분에, 내가 스스로 아무 생각 그들이 자동 양산 스레드 없었다,이 위대하다! 주요 내용으로, 나는 몇 가지 다른 접근법에 대한 조언을 고맙게 생각합니다. 지금 당장은 내 방법을 테스트하고, 앞으로는 더 우아하게 뭔가를 할 것입니다! – Adrian

0

혹시 자신이 다른 상황에서 다시 실행을 지연하고자 찾을 경우이 같은 구현 고려할 수 :

private static void DelayExecution(Action action, TimeSpan delay) 
{ 
    TimeSpan start = DateTime.Now.TimeOfDay; 
    Thread t = new Thread(() => 
    { 
     while (DateTime.Now.TimeOfDay < start.Add(delay)) 
     { 
      //Block 
     } 
     action.Invoke(); 
    }); 
    t.Start(); 
} 

private static void Main(string[] args) 
{ 
    DelayExecution(() => Console.WriteLine("Delayed Execution"), TimeSpan.FromSeconds(1)); 
    Console.ReadLine(); 
} 
+0

감사합니다. – Adrian