2011-03-23 17 views
6

के बिना प्रतीक्षा को कार्यान्वित करने के लिए कैसे करें आप Async CTP await कीवर्ड के समान काम करने वाले कुछ को कैसे कार्यान्वित करेंगे? क्या कोई साधारण कार्यान्वयन है जो सभी मामलों में await जैसा काम करता है, या await को विभिन्न परिदृश्यों के लिए विभिन्न कार्यान्वयन की आवश्यकता है?Async CTP

+2

मैंने अभी एक लेख प्रकाशित किया है कि कैसे [Iterators का उपयोग कर सी # 4 में कार्य प्रतीक्षा करें] (http://www.codeproject.com/Articles/504197/Await-Tasks-in-Csharp4-using-Iterators)। हैरानी की बात यह है कि यह न तो "हैकी" है और न ही बहुत बदसूरत है, और AFAICT बस इंतजार कर रहा है। इसकी जांच - पड़ताल करें! –

उत्तर

8

await में हमेशा एक ही प्रकार का परिवर्तन शामिल होता है - लेकिन यह एक बहुत दर्दनाक है। लाइब्रेरीawait की तरफ बहुत जटिल नहीं है, लेकिन मुश्किल बात यह है कि कंपाइलर आपके लिए एक राज्य मशीन बनाता है, जिससे निरंतरता सही जगह पर वापस कूदने की अनुमति देती है।

यह संभव है कि इटरेटर ब्लॉक (उपज वापसी) के कुछ हैकी उपयोग आप नकली कुछ ऐसा कर सकते हैं ... लेकिन यह बहुत बदसूरत होगा।

मैंने DevExpress webinar on what the compiler is doing behind the scenes a few weeks ago दिया - जो कि कुछ उदाहरणों से विकृत कोड दिखाता है, साथ ही समझाता है कि कंपाइलर कैसे काम करने के लिए एक कार्य बनाता है, और "प्रतीक्षाकर्ता" को क्या करना है। यह आपके लिए उपयोगी हो सकता है।

+0

आप वेबिनार जॉन को यहां यूट्यूब पर उल्लिखित कर सकते हैं: http://www.youtube.com/watch?v=HpA2x_JvLD4 – ShitalShah

2

इटरेटर (उपज) से बने कोरआउटिन के कुछ कार्यान्वयन और उदाहरण हैं।

उदाहरणों में से एक कैलिबर्न है। माइक्रो फ्रेमवर्क, जो इस पटर का उपयोग एसिंक्रोनस जीयूआई ऑपरेशंस के लिए करता है। लेकिन इसे सामान्य एसिंक कोड के लिए आसानी से सामान्यीकृत किया जा सकता है।

2

MindTouch DReAM ढांचे इटरेटर पैटर्न के शीर्ष जो कार्यात्मक रूप से बहुत Async/इंतजार समान है पर Coroutines लागू करता है:

async Task Foo() { 
    await SomeAsyncCall(); 
} 

बनाम

IYield Result Foo() { 
    yield return SomeAsyncCall(); 
} 

ResultTask का सपना का संस्करण है। फ्रेमवर्क डीएलएस .NET 2.0+ के साथ काम करते हैं, लेकिन इसे बनाने के लिए आपको 3.5 की आवश्यकता है, क्योंकि हम इन दिनों 3.5 से अधिक वाक्यविन्यास का उपयोग कर रहे हैं।

9

नया await कीवर्ड में मौजूदा yield return कीवर्ड में समान अर्थशास्त्र है जिसमें वे दोनों आपके लिए स्थिरता शैली स्थिति मशीन उत्पन्न करने के लिए कंपाइलर का कारण बनते हैं। इसलिए इटिनेटर का उपयोग करके एक साथ कुछ हैक करना संभव है जिसमें असिन सीटीपी के समान व्यवहार हैं।

यहां यह कैसा दिखता है।

public class Form1 : Form 
{ 
    private void Button1_Click(object sender, EventArgs e) 
    { 
     AsyncHelper.Invoke<bool>(PerformOperation); 
    } 

    private IEnumerable<Task> PerformOperation(TaskCompletionSource<bool> tcs) 
    { 
     Button1.Enabled = false; 
     for (int i = 0; i < 10; i++) 
     { 
      textBox1.Text = "Before await " + Thread.CurrentThread.ManagedThreadId.ToString(); 
      yield return SomeOperationAsync(); // Await 
      textBox1.Text = "After await " + Thread.CurrentThread.ManagedThreadId.ToString(); 
     } 
     Button2.Enabled = true; 
     tcs.SetResult(true); // Return true 
    } 

    private Task SomeOperationAsync() 
    { 
     // Simulate an asynchronous operation. 
     return Task.Factory.StartNew(() => Thread.Sleep(1000)); 
    } 
} 

yield return के बाद से उत्पन्न एक IEnumerable हमारे coroutine एक IEnumerable लौट जाना चाहिए। सभी जादू AsyncHelper.Invoke विधि के अंदर होता है। यही वह है जो हमारे कोरआउटिन (एक हैकड इटरेटर के रूप में मास्कराइडिंग) हो जाता है। यह सुनिश्चित करने के लिए विशेष देखभाल होती है कि इटेटर को हमेशा मौजूदा सिंक्रनाइज़ेशन संदर्भ पर निष्पादित किया जाता है यदि कोई मौजूद होता है तो यह संकेत मिलता है कि await यूआई थ्रेड पर कैसे काम करता है। यह पहले MoveNext को समकालिक रूप से निष्पादित करके और फिर SynchronizationContext.Send का उपयोग करके कार्यकर्ता धागे से बाकी करने के लिए करता है जिसे अलग-अलग चरणों पर अतुल्यकालिक रूप से प्रतीक्षा करने के लिए भी उपयोग किया जाता है।

public static class AsyncHelper 
{ 
    public static Task<T> Invoke<T>(Func<TaskCompletionSource<T>, IEnumerable<Task>> method) 
    { 
     var context = SynchronizationContext.Current; 
     var tcs = new TaskCompletionSource<T>(); 
     var steps = method(tcs); 
     var enumerator = steps.GetEnumerator(); 
     bool more = enumerator.MoveNext(); 
     Task.Factory.StartNew(
      () => 
      { 
       while (more) 
       { 
        enumerator.Current.Wait(); 
        if (context != null) 
        { 
         context.Send(
          state => 
          { 
           more = enumerator.MoveNext(); 
          } 
          , null); 
        } 
        else 
        { 
         enumerator.MoveNext(); 
        } 
       } 
      }).ContinueWith(
      (task) => 
      { 
       if (!tcs.Task.IsCompleted) 
       { 
        tcs.SetResult(default(T)); 
       } 
      }); 
     return tcs.Task; 
    } 
} 

TaskCompletionSource के बारे में पूरी तरह से थोड़ा await "वापसी" एक मूल्य के कर सकते हैं नकल में मेरी कोशिश थी।समस्या यह है कि कोरआउट में है जो वास्तव में IEnumerable लौटाता है क्योंकि यह एक हैक किए गए इटरेटर से अधिक कुछ नहीं है। तो मुझे वापसी मूल्य पर कब्जा करने के लिए एक वैकल्पिक तंत्र के साथ आने की जरूरत थी।

इसके साथ कुछ चमकदार सीमाएं हैं, लेकिन मुझे उम्मीद है कि यह आपको सामान्य विचार देता है। यह भी दर्शाता है कि सीएलआर में कोरोटाइन्स को लागू करने के लिए एक सामान्यीकृत तंत्र है जिसके लिए await और yield return सर्वव्यापी उपयोग करेंगे, लेकिन विभिन्न तरीकों से अपने संबंधित अर्थशास्त्र प्रदान करने के लिए।

0

मेरे पढ़ने से, yield return और await के बीच प्रमुख अंतर यह है कि await स्पष्ट रूप से निरंतरता में एक नया मान प्रदान कर सकता है।

SomeValue someValue = await GetMeSomeValue(); 

yield return साथ जबकि, आप संदर्भ द्वारा इसी कार्य को पूरा करना होगा।

var asyncOperationHandle = GetMeSomeValueRequest(); 
yield return asyncOperationHandle; 
var someValue = (SomeValue)asyncOperationHandle.Result; 
1

विधेयक वैगनर Microsoft से कैसे आप async सीटीपी पर निर्भरता को जोड़े बिना व्यवहार की तरह async लागू करने के लिए दृश्य स्टूडियो 2010 में टास्क समानांतर लाइब्रेरी का उपयोग कर सकते के बारे में an article in MSDN Magazine लिखा था।

यह Task और Task<T> का उपयोग करता है बड़े पैमाने पर जो भी अतिरिक्त लाभ है कि एक बार सी # 5 बाहर है, अपने कोड अच्छी तरह से async और await का उपयोग शुरू करने के लिए तैयार हो जाएगा।