2013-02-24 5 views
1

Thread.sleep을 사용하지 않고 다음을 수행하고 싶습니다. 기본적으로 각 함수 사이에 대기 시간이있는 3 개의 함수를 호출하고 100 회 동안 루프를 통해 모든 것을 실행해야합니다.함수 사이에서 대기하는 방법

Timer 클래스를 사용해 보았지만 잘못 사용하고있는 것으로 보입니다.

func test() 
for(int i=0;i<100;i++){ 
     func A() 
     wait for 20 seconds 
     func B() 
     wait for 45 seconds 
     func C() 
     wait for 2 mins 
}//repeat for 100 times 
+5

왜 Thread.Sleep을 사용할 수 없습니까? 기다리는 동안 스레드를 해제하므로 지연이 필요한 경우 이상적으로 보입니다. – driis

+0

왜 Thread.Sleep을 사용하고 싶지 않으십니까? 그것이 정확하게 설계된 것입니다. –

+4

@driis : 스레드를 "해제"하지 않습니다. 다른 작업에서 스레드를 사용할 수있는 것과는 다릅니다. 중요한 CPU를 사용하지는 않지만 "해제"한다고는하지 않습니다. –

답변

0

나는거야 가서 큰 가정 (모든 단서는 그 방향으로 포인트)합니다

난 당신이 윈도우 폼에이 모든 일을하는지 추정하고있어 그리고 당신은 GUI를 싶습니다 Thread.Sleep() 호출 도중 멈추지 않는가? 그 경우라면 당신은이 방법을 쓸 수있다 :

public static class Foo { 
    public static void MySleep(int milliseconds) { 
    int startTick = Environment.TickCount; 
    while (Environment.TickCount - startTick < milliseconds) 
     Application.DoEvents(); 
    } 
} 

을 다음 Foo.MySleep 호출로 Thread.sleep를 호출을 대체 (그러나 전체 과정을 수 있습니다 Application.DoEvents의 의미의을 조심 예방 조치를 취하지 않으면이 작업을 수행하지 않는 것이 좋습니다. 예를 들어 func 테스트를 호출하는 단추를 항상 비활성화해야합니다 (예 :)테스트이 실행 중입니다. 왜냐하면 결코 끝나지 않는 재귀에서 반복 실행될 수 있기 때문입니다) :

func test() 
    for(int i=0;i<100;i++){ 
    func A() 
    Foo.MySleep(20 * 1000); 
    func B() 
    Foo.MySleep(45 * 1000); 
    func C() 
    Foo.MySleep(2 * 60 * 1000); 
}//repeat for 100 times 

이렇게하는 또 다른 방법이 있습니다. 보조 스레드 및 일부 Control.Invoke 호출이 관련됩니다. 또한 표준 System.Thread.Sleep (int 밀리 초) 메서드를 사용할 수 있습니다.

그리고이 같은 간다 :

public class Form1 : Form { 

    public void triggerTestAndReturnImmediately() { 
    new Thread(start:() => { 

     Action callA =() => funcA(); 
     Action callB =() => funcB(); 
     Action callC =() => funcC(); 

     for(int i=0;i<100;i++){ 
     this.Invoke(callA); 
     Thread.Sleep(20 * 1000); 

     this.Invoke(callB); 
     Thread.Sleep(45 * 1000); 

     this.Invoke(callC); 
     Thread.Sleep(2 * 60 * 1000); 
     }//repeat for 100 times 


    }).Start(); 
    } 

} 

은 "this.Invoke (someDelegate)"비트는 방법 "triggerTestAndReturnImmediately는"양식 서브 클래스의 일원이라는 사실에 근거하고있다을 "이" Form 인스턴스입니다.

여기서 계속되는 것은 실제 작업자 (funcA, funcB, funcC)의 대기 작업 + 트리거를 별도의 스레드에서 실행한다는 것입니다. 왜 당신은 실제 근로자가 아닌 실제 근로자의 삼총사 만 운영합니까? 왜냐하면 당신은 그 기능들로부터 GUI 객체에 접근 할 가능성이 가장 높기 때문에 WinForms (그리고 많은 다른 .NET 또는 그 외의 .NET GUI 프레임 워크에서는 허용되지 않습니다).

GUI 스레드 (질문에서 지적한대로)는 해당 기능을 실행하는 데 99 %의 시간이 소요되어야합니다. 따라서 this.Invoke (someDelegate) 호출을 자유롭게 사용해야합니다.

앞에서 언급 한 것과 동일한 예방 조치를 취해야하지만 모든 내용은 사용자에게 달려 있으며 응용 프로그램에서 수행해야 할 사항입니다. 단추의 Click 이벤트 처리기를 triggerTestAndReturnImmediately으로 호출하고 프로세스 중에이 단추를 사용하지 않으려면 단추를 사용하지 않도록 설정하고 다시 사용하도록 설정 하시겠습니까?

는이 작업을 수행 할 경우 : triggerTestAndReturnImmediately 방법은 그 이름에서 알 수 있듯이 그냥 무엇 않기 때문에

void buttonBar_Click(object sender, EventArgs e) { 
    this.buttonBar.Enabled = false; 
    this.triggerTestAndReturnImmediately(); 
    this.buttonBar.Enabled = true; 
} 

은 즉, 어떤 좋은 일을하지 것이다 : "즉시 반환".

그럼 어떻게하지 않으시겠습니까? 당신이 뭔가를 할 수 있습니다 :

void buttonBar_Click(object sender, EventArgs e) { 
    this.triggerTestAndReturnImmediately(); 
} 


    public void triggerTestAndReturnImmediately() { 
    this.buttonBar.Enabled = false; 

    new Thread(start:() => { 

     Action callA =() => funcA(); 
     Action callB =() => funcB(); 
     Action callC =() => funcC(); 
     Action reenableButton =() => this.buttonBar.Enabled = true; 

     for(int i=0;i<100;i++){ 
     this.Invoke(callA); 
     Thread.Sleep(20 * 1000); 

     this.Invoke(callB); 
     Thread.Sleep(45 * 1000); 

     this.Invoke(callC); 
     Thread.Sleep(2 * 60 * 1000); 

     this.Invoke(reenableButton); 
     }//repeat for 100 times 


    }).Start(); 
    } 

또한 만들 호출 순서가 일부 마침내 문 또는 다른 체조를 시도하여 충돌 여부 항상 버튼을 다시 활성화해야합니다.

그래서 내가하고있는 예방 조치가 무엇인지 아이디어를 얻을 수 있다고 생각합니다. 귀하의 앱이 원하는 것을 따라 달라집니다.

2

당신은 Task 프레임 워크를 찾고있을 것입니다. 다음과 같이 할 수 있습니다.

async void Run() 
{ 
    for (int i=0; i<100; i++) 
    { 
     A(); 
     await Task.Delay(TimeSpan.FromSeconds(20)); 
     B(); 
     await Task.Delay(TimeSpan.FromSeconds(45)); 
     C(); 
     await Task.Delay(TimeSpan.FromMinutes(2)); 
    } 
} 

이 함수는 즉시 반환하지만 해당 루프는 백그라운드에서 계속 실행됩니다.

편집 : 아래에 언급 된 svick은 새로운 .NET 4.5 기능입니다.

+0

좋은 답변입니다. 이것은 본질적으로 필자가 작성한 것이지만, 명시 적으로 'Timer'를 사용하고 있는데, 이것은 작업의 끔찍한 부분으로 드러납니다. –

+0

이 작업을 수행하려면 VS2012가 필요하다는 것을 추가 할 수 있습니다. – svick

관련 문제