2012-11-16 37 views
50

Tôi nhận thấy trong .NET 4.5 rằng WPF Dispatcher đã nhận được một tập hợp các phương pháp mới để thực thi nội dung trên chuỗi của Dispatcher được gọi là InvokeAsync. Trước đây, .NET 4.5, chúng tôi đã có InvokeBeginInvoke xử lý điều này một cách đồng bộ và không đồng bộ.Sự khác biệt giữa InvokeAsync và BeginInvoke cho WPF Dispatcher

Bên cạnh việc đặt tên và quá tải hơi khác nhau có sẵn, có bất kỳ sự khác biệt lớn giữa các phương pháp BeginInvokeInvokeAsync không?

Oh, và tôi đã kiểm tra, cả hai có thể await ed:

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

Trả lời

40

Không có sự khác biệt như là phương pháp BeginInvoke gọi một LegacyBeginInvokeImpl phương pháp riêng mà itslef gọi phương thức riêng InvokeAsyncImpl (phương pháp được sử dụng bởi InvokeAsync). Vì vậy, về cơ bản là điều tương tự. Nó có vẻ như nó là một tái cấu trúc đơn giản, tuy nhiên nó là lạ các phương pháp BeginInvoke không được gắn cờ là lỗi thời.

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

Hiện tại tôi đang nhận được các ngoại lệ chưa được xử lý hoạt động như mong đợi bằng BeginInvoke (kích hoạt cả DispatcherUnh andledException trên dispatcher và AppDomain.CurrentDomain.UnhandledException), nhưng các ngoại lệ chưa được giải quyết trên InvokeAsync đang bị âm thầm nuốt chửng. Tiếp tục nhiệm vụ từ InvokeAsync với một cái gì đó để bẫy ngoại lệ có vẻ là một công việc hợp lệ xung quanh. – Lamarth

+2

'BeginInvoke' được tạo khuôn mẫu sau [" Mô hình lập trình không đồng bộ "] (https://msdn.microsoft.com/en-us/library/ms228963 (v = vs.110) .aspx) trong .NET sử dụng' BeginSomething Phương thức 'và' EndSomething' cho các phép toán không đồng bộ. Có lẽ đây là lý do tại sao nó không được chỉ định không được chấp nhận hoặc lỗi thời. Ngoại trừ quy ước 'Begin' /' End' là sử dụng 'IAsyncResult', và' BeginInvoke' không, cũng không có bất kỳ 'EndInvoke' nào, vì vậy nó là loại thừa định ngay từ đầu. – sidbushes

-1

[Edit - cả hai đều giống nhau]

Thereotically

công trình BeginInvoke trên chuỗi mà người điều phối đã được tạo và InvokeAsync hoạt động với luồng mà bộ điều phối được liên kết.

Điều đó có nghĩa là nếu bạn cần xử lý mọi thứ dựa trên luồng hiện tại của điều phối viên, bạn sẽ sử dụng InvokeAsync khác sử dụng BeginInvoke.

EDIT: - nhưng ở trên nhận xét là vô nghĩa vì bạn không thể thay đổi chuỗi liên kết của điều phối khi nó được tạo.

Đồng ý với câu trả lời đề cập ở trên .. nhờ

+0

Bạn có thể cung cấp một số tài liệu tham khảo không? –

+0

Tôi cũng sẽ bị can thiệp vì mã được truy xuất nhờ ILSpy không có sự khác biệt giữa hai phương thức – Sisyphe

+2

Tôi không nghĩ đó là sự thật. MSDN nói "Executes ... trên chuỗi Dispatcher ** được liên kết với **" trên khoảng một nửa của quá tải 'BeginInvoke' và" Executes ... trên chuỗi mà Dispatcher đã được tạo ** " ở nửa còn lại. Tôi khá chắc chắn rằng nó chỉ đơn giản có nghĩa là như nhau. – Clemens

11

Có một sự khác biệt trong phương pháp chữ ký:

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

Đối BeginInvoke() trình biên dịch tạo ra mảng Object[] ngầm trong khi đối với InvokeAsync() mảng như vậy là không cần thiết:

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) 
Các vấn đề liên quan