2009-10-26 6 views
0

비동기 메서드를 호출하고 싶지만 타이머를 사용하고 싶지 않습니다. 어떻게 타이머를 대체 할 수 있습니까? 타이머를 대체하는 호출자가 필요합니다.타이머 대체

답변

1

비동기 메서드를 호출하는 데 타이머가 필요하지 않습니다.이를 수행하는 데 사용할 수있는 다양한 메커니즘이 있습니다. 타이머는 특정 시간에 무언가를 호출하거나 특정 간격으로 반복적으로 호출하는 데 사용됩니다. 비동기 적으로 호출하거나 특정 시간에 호출하려면 요구 사항은 무엇입니까 ??

+0

내 요구 사항은 특정 시간 (들)에서 비동기 적으로 호출하는 것입니다. 전화해야하는 5 가지 방법이 있습니다. 타이머를 사용할 경우 5 개를 사용해야합니다. – Wilson

5

.NET 비동기 프로그래밍 모델을 살펴 봐야합니다. 소리가 훨씬 간단합니다. 비동기 적으로 실행하려는 메서드에 대한 대리자를 만들면됩니다. 그런 다음 대리자에서 BeginInvoke를 호출하면 메서드가 백그라운드 스레드에서 자동으로 실행됩니다.

비동기 메서드에서 UI를 업데이트해야하는 경우 관련 양식이나 컨트롤에서 Control.Invoke/BeginInvoke를 사용해야합니다.

또한 비동기 메서드에서 UI 스레드로 결과를 반환해야하는 경우 BeginInvoke에서 반환 된 IAsyncResult 및 EndInvoke 메서드를 사용해야합니다.

자세한 내용은 Calling Synchronous Methods Asynchronously 문서를 참조하십시오. 방금 Windows.Forms에서 자바 스크립트 방법 window.settimeout()에 해당 찾는 경우

한편

는 다음 완전히 재사용 가능한 방법으로 표준 타이머를 포장하여 스레드를 방지 :

public void SetTimeout(EventHandler doWork, int delayMS) 
{ 

    System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer(); 

    timer.Interval = delayMS; 

    timer.Tick += delegate(object s, EventArgs args) { timer.Stop(); }; 

    timer.Tick += doWork; 

    timer.Start(); 

} 

은 다음 전화 :

SetTimeout(delegate { YourMethod(); }, 100); 

을 그냥 폼에 드래그 타이머처럼, YourMethod는() 형태의 메시지 루프에 의해 UI 스레드에서 실행됩니다. 따라서 BeginInvoke/Invoke에 대해 걱정할 필요가 없습니다.

+0

@ Serge, Control.BeginInvoke 및 Delegate.BeginInvoke가 혼란스러워지고 있습니다. Control.BeginInvoke는 기본 UI 스레드에서 실행되지만 Delegate 버전은 작업자/백그라운드 스레드에서 실행됩니다. 자세한 내용은 링크 된 기사를 참조하십시오. – Ash

+0

애쉬, 나는 고쳐 쓴다. 문제의 코멘트를 삭제했습니다. –

0

Control.BeginInvoke()은 앱에 GUI가있는 경우 친구입니다. 함수에 대한 위임을 제공하면 .NET은 현재 이벤트 처리기가 실행을 마친 후에 호출합니다.

NB : Delegate.BeginInvoke()와 대조적으로 Control.BeginInvoke()는 주 스레드 (실제로 컨트롤이 만들어진 스레드)에서 실행됩니다.

대부분의 경우 나는 개인 스레드에서 비동기 실행과 동일한 스레드에서 실행을 선호합니다. 가능한 적은 부작용입니다. 귀하의 마일리지가 다를 수 있습니다.

void f(string s) 
{ 
    Debug.WriteLine(s + " -> Thread = " + 
    System.Threading.Thread.CurrentThread.Name); 
} 

private void button_Click(object sender, EventArgs e) 
{ 
    Debug.WriteLine("Start button_Click"); 
    f("straight call in button_Click"); 
    BeginInvoke(new Action<string>(f), "async call through BeginInvoke()"); 
    Debug.WriteLine("End button_Click"); 
} 

출력 :

Start button_Click 
straight call in button_Click -> Thread = Main Thread 
End button_Click 
async call through BeginInvoke() -> Thread = Main Thread 

참고 : 이름 "메인 스레드는"프로그램의 홈페이지()에서 스레드에 할당됩니다.

+0

@ Serge, 당신은 Control.BeginInvoke와 Delegate.BeginInvoke를 혼동합니다. 귀하의 예제는 실제로 this.BeginInvoke()를 실행합니다. 'this'는 귀하의 양식입니다. 폼은 컨트롤을 상속받습니다. BeginInvoke (또는 invoke)를 사용하면 무의미합니다. Control.BeginInvoke()는 주로 배경/작업자 스레드에서 호출 할 때 유용합니다. .NET은 백그라운드/작업자 스레드에서 메서드를 호출하는 데 사용할 수있는 BeginInvoke()/Invoke() 메서드가 정의 된 대리자가되도록 APM (내 대답 참조)을 제공합니다. Jeff Richter의 CLR Via C#에서이 책에 대한 훌륭한 기사를 볼 수 있습니다. – Ash

+0

재, 나를 고쳐 주셔서 고마워요. 그리고 사과! 나는 변명의 여지가 없다 : 10k 사람들은 보통 그런 기본적인 실수를하지 않는다. + 책은 내 책꽂이에있다! 내 대답을 편집하여 내 의견을 반영했습니다 –

+0

@ Serge, 내 기쁨. 희망은 내가 "그것을 모두 알고"로 건너 오지 않았어, 날 믿어, 너무 StackOverflow에서 배웠습니다. 실제로 테스트 코드를 작성하고 CLR 비아 C#을 사용하기 전까지는 대의원을 잘 이해하지 못했습니다. 10K + 사람이되는 것에 대한 마법은 없습니다. 2 주 동안 한 번만했습니다.) – Ash

0

다른 답변은 충분하지만 아래 도움말을 보니 가치가있을 수 있습니다. C#에서 지정된 간격으로 실행되는 일반 폴링 구성 요소와 백그라운드 스레드를 사용하여 지정된 사용자 작업을 수행하는 방법을 보여줍니다.

샘플 사용 : 코드와 전체 샘플을 참조하십시오

IPoller poller = new UrlPoller(args[0], TimeSpan.FromSeconds(7)); 
IPolling pollingComponent = new Polling.Core.Polling(poller); 
pollingComponent.SubscribeForPollingUpdates(PollingAction); 
pollingComponent.Start(); 

:

http://www.avantprime.com/blog/24/an-example-of-repeating-code-using-a-worker-thread-without-using-timers-c