2012-11-16 1 views
50

WPF DispatcherInvokeAsync이라는 Dispatcher의 스레드에서 물건을 실행하는 새로운 세트의 메소드를 얻었음을 .NET 4.5에서 확인했습니다. 이전에는 .NET 4.5에서 각각 InvokeBeginInvoke을 사용하여이를 동기 및 비동기로 각각 처리했습니다.WPF Dispatcher의 InvokeAsync와 BeginInvoke의 차이점

사용할 수있는 이름과 약간 다른 오버로드 외에도 BeginInvokeInvokeAsync 방법간에 큰 차이점이 있습니까?

아, 그리고 이미 확인, 모두 await 에드 될 수 있습니다

private async Task RunStuffOnUiThread(Action action) 
{ 
    // both of these works fine 
    await dispatcher.BeginInvoke(action); 
    await dispatcher.InvokeAsync(action); 
} 

답변

40

BeginInvoke 방법은 itslef 민간 방법 InvokeAsyncImpl (InvokeAsync에 의해 사용되는 방법을 호출하는 개인 LegacyBeginInvokeImpl 메소드를 호출로 차이가 없습니다). 기본적으로 똑같습니다. 그것은 단순한 리팩토링 인 것처럼 보이지만, BeginInvoke 메소드는 쓸데없는 것으로 표시되지 않았다는 것이 이상합니다.

BeginInvoke :

public DispatcherOperation BeginInvoke(DispatcherPriority priority, Delegate method) 
{ 
    return this.LegacyBeginInvokeImpl(priority, method, null, 0); 
} 

private DispatcherOperation LegacyBeginInvokeImpl(DispatcherPriority priority, Delegate method, object args, int numArgs) 
{ 
    Dispatcher.ValidatePriority(priority, "priority"); 
    if (method == null) 
    { 
     throw new ArgumentNullException("method"); 
    } 
    DispatcherOperation dispatcherOperation = new DispatcherOperation(this, method, priority, args, numArgs); 
    this.InvokeAsyncImpl(dispatcherOperation, CancellationToken.None); 
    return dispatcherOperation; 
} 

InvokeAsync :

public DispatcherOperation InvokeAsync(Action callback, DispatcherPriority priority) 
{ 
    return this.InvokeAsync(callback, priority, CancellationToken.None); 
} 

public DispatcherOperation InvokeAsync(Action callback, DispatcherPriority priority, CancellationToken cancellationToken) 
{ 
    if (callback == null) 
    { 
     throw new ArgumentNullException("callback"); 
    } 
    Dispatcher.ValidatePriority(priority, "priority"); 
    DispatcherOperation dispatcherOperation = new DispatcherOperation(this, priority, callback); 
    this.InvokeAsyncImpl(dispatcherOperation, cancellationToken); 
    return dispatcherOperation; 
} 
+5

현재 처리되지 않은 예외가 BeginInvoke를 사용하여 예상대로 작동하고 있습니다 (DispatcherUnh andledException) 및 AppDomain.CurrentDomain.UnhandledException), InvokeAsync에서 처리되지 않은 예외가 자동으로 삼키는 중입니다. 예외를 트래핑하는 무언가로 InvokeAsync에서 작업을 계속하면 유효한 해결 방법 인 것 같습니다. – Lamarth

+2

'BeginInvoke'는 .NET에서''BeginSomething ''을 사용하는 [ "Asynchronous Programming Model"] (https://msdn.microsoft.com/en-us/library/ms228963(v=vs.110) .aspx) '및'EndSomething' 메소드를 호출합니다. 아마도 이것이 비추천되거나 쓸모없는 것으로 지정되지 않은 이유 일 것입니다. 'Begin' /'End' 컨벤션은'IAsyncResult'을 사용하기위한 것이고'BeginInvoke'는'EndInvoke'도 아니고, 그래서 EndInvoke도 없습니다. 그래서 처음에는 불필요한 일이었습니다. – sidbushes

-1

[편집 - 모두 동일]

Thereotically

BeginInvoke 작업 Dispatcher가 작성된 스레드 및 Dispatcher가 연결된 스레드에서 InvokeAsync가 작동합니다.

즉, Dispatcher의 현재 스레드를 기반으로 처리해야 할 경우 InvokeAsync를 사용하고 BeginInvoke를 사용합니다.

EDIT : -하지만 위의 설명은 생성 된 발송자와 관련된 스레드를 변경할 수 없기 때문에 의미가 없습니다.

위에서 언급 대답에 동의

.. 감사

+0

몇 가지 참조를 제공해 주시겠습니까? –

+0

ILSpy 덕분에 검색된 코드가 두 가지 방법간에 차이가 없음을 나타내므로 나는 또한 인터 레스트 될 것입니다. – Sisyphe

+2

나는 그것이 사실이라고 생각하지 않습니다. MSDN에서 "BeginInvoke"메소드 오버로드의 대략 절반에서 Dispatcher가 ** 연결된 ** 스레드에서 Executes ...를 실행하고 Dispatcher가 ** 생성 된 스레드에서 "Executes ...를 실행합니다"라고 말합니다. 나머지 절반은. 나는 그것이 단순히 똑같은 것을 의미한다고 확신합니다. – Clemens

11

메소드 서명에 차이가있다 : 컴파일러는 암시 InvokeAsync()에 대한 이러한 배열이 필요하지 않을 때 배열 Object[]을 생성

BeginInvoke(Delegate, Object[]) 
InvokeAsync(Action) 

BeginInvoke()의 경우 :

IL_0001: ldarg.0 
IL_0002: call  instance class [WindowsBase]System.Windows.Threading.Dispatcher [WindowsBase]System.Windows.Threading.DispatcherObject::get_Dispatcher() 
IL_0007: ldarg.1 
IL_0008: ldc.i4.0 
IL_0009: newarr  [mscorlib]System.Object 
IL_000e: callvirt instance class [WindowsBase]System.Windows.Threading.DispatcherOperation [WindowsBase]System.Windows.Threading.Dispatcher::BeginInvoke(class [mscorlib]System.Delegate, object[]) 


IL_0014: ldarg.0 
IL_0015: call  instance class [WindowsBase]System.Windows.Threading.Dispatcher [WindowsBase]System.Windows.Threading.DispatcherObject::get_Dispatcher() 
IL_001a: ldarg.1 
IL_001b: callvirt instance class [WindowsBase]System.Windows.Threading.DispatcherOperation [WindowsBase]System.Windows.Threading.Dispatcher::InvokeAsync(class [mscorlib]System.Action)