2010-12-01 2 views
4

스레드가 포함 된 클래스를 사용하는 폼이있는 C# 2.0 응용 프로그램이 있습니다.스레드에서 Invoke/BeginInvoke 호출

스레드 함수에서 이벤트 핸들러를 직접 호출하지 않고 호출합니다. 결과적으로 소유 양식은 컨트롤을 업데이트하기 위해 InvokeRequired/BeginInvoke를 호출 할 필요가 없습니다.

public class Foo 
{ 
    private Control owner_; 
    Thread thread_; 

    public event EventHandler<EventArgs> FooEvent; 

    public Foo(Control owner) 
    { 
     owner_ = owner; 
     thread_ = new Thread(FooThread); 
     thread_.Start(); 
    } 

    private void FooThread() 
    { 
     Thread.Sleep(1000); 
     for (;;) 
     { 
      // Invoke performed in the thread 
      owner_.Invoke((EventHandler<EventArgs>)InternalFooEvent, 
       new object[] { this, new EventArgs() }); 
      Thread.Sleep(10); 
     } 
    } 

    private void InternalFooEvent(object sender, EventArgs e) 
    { 
     EventHandler<EventArgs> evt = FooEvent; 
     if (evt != null) 
      evt(sender, e); 
    } 
} 

public partial class Form1 : Form 
{ 
    private Foo foo_; 

    public Form1() 
    { 
     InitializeComponent(); 

     foo_ = new Foo(this); 
     foo_.FooEvent += OnFooEvent; 
    } 

    private void OnFooEvent(object sender, EventArgs e) 
    { 
     // does not need to call InvokeRequired/BeginInvoke() 
     label_.Text = "hello"; 
    } 
} 

이 System.Timers.Timer 및 System.Io.Ports.SerialPort처럼 배경 스레드를 사용하는 마이크로 소프트 API에서 사용되는 방법에 분명히 반대입니다. 본질적으로이 방법에 문제가 있습니까? 그것은 어떤면에서 위험한가요?

감사합니다, PaulH


편집

: 또한, 형태가 바로 이벤트에 무엇을 가입하지 않은 경우? 양식에 관심이없는 이벤트가있는 양식의 메시지 대기열을 막히게합니까?

+0

내 편집을 참조하십시오. – Falcon

답변

3

이것은 threadsafe 호출이며 메서드는 폼의 스레드에서 처리됩니다.

개념적 관점에서 볼 때 아무런 문제가 없습니다.

타이머는 그런 작업을 위해 더 우아합니다. 그러나 10ms 간격의 타이머를 사용하면 GUI가 느려질 수 있습니다. 아마도 Invoke가 사용 된 것입니다.

컨트롤이 다른 스레드에 있음이 분명하기 때문에 InvokeRequired를 호출 할 필요가 없습니다. 또한 BeginInvoke는 메소드를 비동기 적으로 호출하려는 경우에만 호출하면됩니다. 여기서는 분명하지 않습니다.

편집 관련 : 아니요, 메시지 대기열이 막히지 않습니다. 핸들러가 등록되어 있지 않으면 이벤트가 시작되지 않습니다. 코드를 다시 살펴보십시오.)

관련 문제