2012-11-16 12 views
50

के लिए InvokeAsync और BeginInvoke के बीच क्या अंतर है मैंने .NET 4.5 में देखा है कि WPF Dispatcher को InvokeAsync नामक डिस्पैचर के थ्रेड पर सामान निष्पादित करने के तरीकों का एक नया सेट प्राप्त हुआ था। इससे पहले, .NET 4.5 हमारे पास Invoke और BeginInvoke था जो क्रमशः इस सिंक्रोनस और असीमित रूप से संभाला गया था।WPF डिस्पैचर

नामकरण और थोड़ा अलग ओवरलोड उपलब्ध होने के अलावा, BeginInvoke और InvokeAsync विधियों के बीच कोई बड़ा अंतर है?

ओह, और मैं पहले ही जाँच, दोनों await एड हो सकता है:

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

उत्तर

40

कोई मतभेद के रूप में BeginInvoke विधि एक निजी LegacyBeginInvokeImpl विधि जो itslef निजी विधि InvokeAsyncImpl (विधि InvokeAsync द्वारा प्रयोग किया जाता कॉल कॉल कर रहे हैं)। तो यह मूल रूप से एक ही बात है। ऐसा लगता है कि यह एक साधारण रिफैक्टरिंग है, हालांकि यह अजीब है कि 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 दोनों को ट्रिगर करना प्रेषक और AppDomain.CurrentDomain.UnhandledException पर AndledException), लेकिन InvokeAsync पर unhandled अपवाद चुपचाप निगल रहे हैं। InvokeAsync से कार्य को जारी रखने के लिए कुछ अपवादों के साथ कार्य को जारी रखना एक वैध काम प्रतीत होता है। – Lamarth

+2

'BeginInvoke' ["असीमित प्रोग्रामिंग मॉडल"] (https://msdn.microsoft.com/en-us/library/ms228963 (v = vs.110) .aspx) के बाद पैटर्न किया गया है .NET में जो' BeginSomething का उपयोग करता है 'और' एंडसोमिंग 'विधियों के रूप में एसिंक्रोनस ऑपरेशंस। संभवतः यही कारण है कि इसे बहिष्कृत या अप्रचलित नामित नहीं किया गया था। सिवाय इसके कि 'प्रारंभ'/'अंत 'सम्मेलन' IAsyncResult' का उपयोग करने के लिए है, और' BeginInvoke' नहीं है, न ही कोई 'EndInvoke' है, इसलिए यह पहली जगह में अनिवार्य था। – sidbushes

-1

[संपादित करें - दोनों एक ही हैं]

Thereotically

BeginInvoke काम करता है थ्रेड पर जिस पर प्रेषक बनाया गया था और InvokeAsync थ्रेड के साथ काम करता है जिस पर प्रेषक जुड़ा हुआ है।

इसका मतलब है कि अगर आपको प्रेषक के वर्तमान धागे के आधार पर कुछ संसाधित करने की आवश्यकता है तो आप InvokeAsync का उपयोग अन्यथा BeginInvoke का उपयोग करेंगे।

संपादित करें: - लेकिन ऊपर टिप्पणी टिप्पणी व्यर्थ है क्योंकि आप इसे बनाए जाने के बाद प्रेषक के संबंधित धागे को नहीं बदल सकते हैं।

ऊपर उल्लेख जवाब के साथ सहमत .. धन्यवाद

+0

क्या आप कुछ संदर्भ प्रदान कर सकते हैं? –

+0

मुझे भी इंटरस्टेस्ट किया जाएगा, क्योंकि आईएलएसपी के लिए धन्यवाद कोड को पुनर्प्राप्त किया गया है, दो तरीकों के बीच कोई अंतर नहीं दिखाता – Sisyphe

+2

मुझे नहीं लगता कि यह सच है। एमएसडीएन का कहना है कि "निष्पादन ... थ्रेड पर ** प्रेषक ** ** से जुड़ा हुआ है" लगभग शुरुआती आधा 'BeginInvoke' विधि अधिभार और "निष्पादन ... थ्रेड पर ** ** पर बनाया गया था" दूसरे छमाही पर। मुझे पूरा यकीन है कि इसका मतलब यह है कि इसका मतलब है। – Clemens

11

वहाँ विधि हस्ताक्षर में एक फर्क है:

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

BeginInvoke() लिए संकलक परोक्ष सरणी Object[] बनाता है, जबकि InvokeAsync() के लिए इस तरह सरणी की जरूरत नहीं है:

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) 
संबंधित मुद्दे