Invoke ()와 BeginInvoke ()의 차이점은 무엇입니까


398

그냥 것 사이의 차이가 궁금 BeginInvoke()하고 Invoke()있습니까?

주로 각각에 사용될 것입니다.

편집 : 스레딩 객체를 만들고 호출 BeginInvoke()하는 것과 델리게이트를 호출하는 것의 차이점은 무엇입니까 ? 아니면 같은 것입니까?

답변:


568

Delegate.Invoke/ BeginInvoke또는 Control.Invoke/ 을 의미 BeginInvoke합니까?

  • Delegate.Invoke: 동일한 스레드에서 동 기적으로 실행합니다.
  • Delegate.BeginInvoke: threadpool스레드 에서 비동기 적으로 실행 합니다.
  • Control.Invoke: UI 스레드에서 실행되지만 호출 스레드는 계속하기 전에 완료를 기다립니다.
  • Control.BeginInvoke: UI 스레드에서 실행되며 호출 스레드는 완료를 기다리지 않습니다.

사용할 수있는 경우 팀의 대답은 언급 BeginInvoke이 대부분 맞되었지만 - Delegate.BeginInvoke, 나는 생각한다.

Windows Forms 앱의 경우 일반적으로을 사용 하는 것이 좋습니다 BeginInvoke. 예를 들어 교착 상태에 대해 걱정할 필요는 없지만 다음 번에 UI를 업데이트 할 때 UI가 업데이트되지 않았 음을 이해해야합니다. 특히 UI 스레드가 표시 목적으로 사용할 데이터를 수정해서는 안됩니다. 예를 들어 Personwith FirstNameLastName속성이 있고 수행 한 경우 :

person.FirstName = "Kevin"; // person is a shared reference
person.LastName = "Spacey";
control.BeginInvoke(UpdateName);
person.FirstName = "Keyser";
person.LastName = "Soze";

그러면 UI에 "Keyser Spacey"가 표시 될 수 있습니다. ( "Kevin Soze"를 표시 할 수있는 외부 기회가 있지만 메모리 모델의 기이함을 통해서만 가능합니다.)

그러나 이런 종류의 문제가 없으면 Control.BeginInvoke올바르게 처리하기가 쉽고 배경 스레드가 아무런 이유없이 기다릴 필요가 없습니다. Windows Forms 팀은 Control.BeginInvoke"불을 피하고 잊어 버리는"방식으로 즉, 전화하지 않고도 사용할 수 있음을 보증했습니다 EndInvoke. 일반적으로 비동기 호출에는 해당되지 않습니다. 일반적으로 모든 BeginXXX에는 일반적으로 콜백에서 해당 EndXXX 호출이 있어야합니다.


4
그렇다면 ppl은 왜 BeingInvoke보다 Invoke를 사용합니까? Invoke를 사용하는 것보다 이점이 없어야합니다. 둘 다 백그라운드에서 프로세스를 실행합니다. 하나는 동일한 스레드에 있고 다른 하나는 다른 스레드에 있습니까?
yeeen

2
@ Jon : Dispatcher.BeginInvoke를 사용하는 동안 코드가 제대로 작동하고 Dispatcher에서 내 응용 프로그램을 호출하면 몇 초 동안 기다렸다가 모든 컨트롤을 초기화 한 다음 시작합니다. ?
SharpUrBrain

6
@SharpUrBrain : Control.BeginInvoke는 Dispatcher.BeginInvoke와 동일하지만 WinForms (Dispatcher는 WPF 및 Silverlight 용)에 해당합니다.
Jon Skeet

4
@SharpUrBrain : 의견을 계속하지 말고 특정 질문을하는 것이 좋습니다. 물론 다른 사람이 먼저 같은 질문을했는지 확인하십시오.
Jon Skeet

2
@AZ : 그렇습니다. "UI 스레드"는 특정 컨트롤 핸들을 소유 한 특정 "UI 스레드"를 의미합니다. 일반적으로 UI 스레드는 하나만 있지만 여러 UI 스레드를 가질 수 있으며 고급 응용 프로그램에는 원하는 이유가 있습니다. 기술적으로 모든 (일반?) 스레드는 UI 메시지 펌프를 시작하고 UI 스레드가 될 수 있으며 나중에 메시지 펌프를 종료하고 더 이상 UI 스레드가 될 수 없습니다. (나는 그것이 스레드 풀 스레드에서 시도 할 것이 아니라고 가정합니다.)
Rob Parker

46

Jon Skeet의 응답을 바탕으로 델리게이트를 호출하고 현재 스레드가 계속되기 전에 실행이 완료되기를 기다리는 경우가 있습니다. 이 경우 호출 호출이 원하는 것입니다.

다중 스레딩 응용 프로그램에서, 특히 해당 대리자가 I / O를 수행하는 경우 (대리자 및 스레드 블록을 만들 수있는) 스레드가 대리자에서 실행을 완료하기를 기다리는 것을 원하지 않을 수 있습니다.

이 경우 BeginInvoke가 유용합니다. 호출하면 대리자에게 시작하도록 지시하지만 스레드는 대리자와 동시에 다른 작업을 수행 할 수 있습니다.

BeginInvoke를 사용하면 코드가 복잡해 지지만 성능이 향상 될 때가 있습니다.


27

차이 Control.Invoke()Control.BeginInvoke(), 인

  • BeginInvoke()GUI 스레드에서 비동기 작업을 예약합니다. 비동기 작업이 예약되면 코드가 계속 진행됩니다. 얼마 후 (정확한시기를 모르는 경우) 비동기 작업이 실행됩니다.
  • Invoke() GUI 스레드에서 비동기 작업을 실행하고 작업이 완료 될 때까지 기다립니다.

논리적 결론은 전달한 대리자 Invoke()가 매개 변수를 벗어나거나 반환 값 BeginInvoke()을 가질 수 있지만 전달하는 대리자는 할 수 없다는 것입니다 (EndInvoke를 사용하여 결과를 검색해야 함).


20

차이의 영향을 볼 수있는 짧고 실제적인 예를 제공하기 위해

new Thread(foo).Start();

private void foo()
{
  this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
    (ThreadStart)delegate()
    {
        myTextBox.Text = "bing";
        Thread.Sleep(TimeSpan.FromSeconds(3));
    });
  MessageBox.Show("done");
}

BeginInvoke를 사용 하면 MessageBox가 텍스트 업데이트와 동시에 팝업됩니다. Invoke를 사용 하면 3 초 동안 잠자기 후 MessageBox가 나타납니다. 따라서 비동기 ( BeginInvoke ) 및 동기 ( Invoke ) 호출 의 효과를 보여줍니다 .


9

Delegate.BeginInvoke ()는 대리자의 호출을 비동기 적으로 대기열에 넣고 즉시 제어를 반환합니다. Delegate.BeginInvoke ()를 사용하는 경우 콜백 메소드에서 Delegate.EndInvoke ()를 호출하여 결과를 가져와야합니다.

Delegate.Invoke ()는 동일한 스레드에서 대리자를 동 기적으로 호출합니다.

MSDN 기사


8

Invoke ()를 사용하는 이유와시기를 추가하기 만하면됩니다.

Invoke () 및 BeginInvoke ()는 모두 지정한 코드를 디스패처 스레드에 마샬링합니다.

그러나 BeginInvoke ()와 달리 Invoke ()는 디스패처가 코드를 실행할 때까지 스레드를 정지시킵니다. 사용자가 일종의 피드백을 제공 할 때까지 비동기 작업을 일시 중지해야하는 경우 Invoke ()를 사용할 수 있습니다.

예를 들어, Invoke ()를 호출하여 확인 / 취소 대화 상자를 표시하는 코드 스 니펫을 실행할 수 있습니다. 사용자가 버튼을 클릭하고 마샬링 된 코드가 완료되면 invoke () 메서드가 반환되고 사용자의 응답에 따라 행동 할 수 있습니다.

C # 챕터 31의 Pro WPF 참조

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.