6

प्रेरणा

सी # 5.0 async/इंतजार निर्माणों भयानक, दुर्भाग्य से अभी तक माइक्रोसॉफ्ट केवल दोनों .NET 4.5 और वी.एस. 2012, और इसके बारे में एक रिलीज उम्मीदवार दिखाए जाते हैं कुछ समय लगेगा जब तक कि इन प्रौद्योगिकियों में इन प्रौद्योगिकियों को व्यापक रूप से अपनाया नहीं जाएगा।async टाइमआउट को लागू गरीब मनुष्य async का उपयोग कर/नेट में निर्माणों का इंतजार 4.0

स्टीफन टब के Asynchronous methods, C# iterators, and Tasks में मुझे एक प्रतिस्थापन मिला है जिसे .NET 4.0 में अच्छी तरह से उपयोग किया जा सकता है। यहां एक दर्जन अन्य कार्यान्वयन भी हैं जो .NET 2.0 में भी दृष्टिकोण का उपयोग करके इसे संभव बनाते हैं, हालांकि वे बहुत पुराने और कम फीचर समृद्ध प्रतीत होते हैं।

उदाहरण

तो अब मेरी .NET 4.0 कोड की तरह दिखता है (टिप्पणी की वर्गों को दिखाने के लिए कि यह कैसे .NET 4.5 में किया जाता है): हालांकि यह काम करता है

//private async Task ProcessMessageAsync() 
private IEnumerable<Task> ProcessMessageAsync() 
{ 
    //var udpReceiveResult = await udpClient.ReceiveAsync(); 

    var task = Task<UdpAsyncReceiveResult> 
       .Factory 
       .FromAsync(udpClient.BeginReceive, udpClient.EndReceive, null); 

    yield return task; 

    var udpReceiveResult = task.Result; 

    //... blah blah blah 

    if (message is BootstrapRequest) 
    { 
     var typedMessage = ((BootstrapRequest)(message)); 

     // !!! .NET 4.0 has no overload for CancellationTokenSource that 
     // !!! takes timeout parameter :(
     var cts 
      = new CancellationTokenSource(BootstrapResponseTimeout); // Error here 

     //... blah blah blah 

     // Say(messageIPEndPoint, responseMessage, cts.Token); 

     Task.Factory.Iterate(Say(messageIPEndPoint, responseMessage, cts.Token)); 
    } 
} 

थोड़ा बदसूरत लग रहा है

सवाल

जब .NET 4.5 में CancellationTokenSource का उपयोग कर एक निर्माता है कि एक समय समाप्ति पैरामीटर के रूप में समयावधि लेता है, ताकिजिसके परिणामस्वरूप वहाँ हैनिर्दिष्ट अवधि के भीतर रद्द हो जाता है।
नेट 4.0 टाइमआउट करने में सक्षम नहीं है, तो .NET 4.0 में ऐसा करने का सही तरीका क्या है?

+0

संबंधित प्रश्न: http://stackoverflow.com/questions/9110472/using-async-await-on-

यह जब मैं F12 दबाएँ CancelAfter() के कार्यान्वयन को देखने के लिए refereance souce कोड है नेट -4 – CodesInChaos

+0

शीर्षक में "टाइमर" को "टाइमआउट" में बदल दिया गया है क्योंकि सवाल टाइमआउट और "टाइमर" (कुछ अवधि के निष्पादन के साथ आवर्ती के लिए उपयोग किया जाता है) के बारे में है, भ्रामक और विचलित –

उत्तर

4

क्या यह वास्तव में async/प्रतीक्षा के साथ कुछ भी करने के लिए है? ऐसा लगता है कि आपको टोकन को रद्द करने का एक तरीका चाहिए, स्वतंत्र रूप से async/प्रतीक्षा करें, है ना? उस स्थिति में, क्या आप बस एक टाइमर बना सकते हैं जो टाइमआउट के बाद रद्द करता है?

new Timer(state => cts.Cancel(), null, BootstrapResponseTimeout, Timeout.Infinite); 

संपादित

मेरे प्रारंभिक प्रतिक्रिया से ऊपर मूल विचार है, लेकिन एक और अधिक मजबूत समाधान Is CancellationTokenSource.CancelAfter() leaky? में पाया जा सकता है (निर्माता आप की मांग कर रहे हैं की वास्तव में नेट 4.5 कार्यान्वयन)। यहां एक फ़ंक्शन है जिसका उपयोग आप उस कोड के आधार पर टाइमआउट टोकन बनाने के लिए कर सकते हैं।

public static CancellationTokenSource CreateTimeoutToken(int dueTime) { 
    if (dueTime < -1) { 
     throw new ArgumentOutOfRangeException("dueTime"); 
    } 
    var source = new CancellationTokenSource(); 
    var timer = new Timer(self => { 
     ((Timer)self).Dispose(); 
     try { 
      source.Cancel(); 
     } catch (ObjectDisposedException) {} 
    }); 
    timer.Change(dueTime, -1); 
    return source; 
} 
+0

आप किस प्रकार का टाइमर प्रस्तावित करते हैं डैक्स का प्रयोग करें? – Lu4

+0

'सिस्टम। थ्रेडिंग। टिमर' वह है जो मैं सोच रहा था, लेकिन मुझे लगता है कि उनमें से किसी को भी काम करना चाहिए - मैं विभिन्न प्रकार के नेट 'टाइमर' के बीच मतभेदों पर एक विशेषज्ञ नहीं हूं। –

+0

लेकिन यह धागे को अवरुद्ध कर देगा और हम असीमित दृष्टिकोण के सभी लाभों को खोना शुरू कर देंगे ... :( – Lu4

5

एफडब्ल्यूआईडब्ल्यू, आप 4.0 परियोजनाओं में एसिंक/प्रतीक्षा का उपयोग कर सकते हैं, बस the async targeting pack का उपयोग करें। मेरे लिए महान काम करता है!

+1

निश्चित रूप से उपयोगी उत्तर – Lu4

0

तुम अब भी CancelAfter(), जो Microsoft.Bcl.Async में एक विस्तार विधि है जो बहुत स्वीकार किए जाते हैं जवाब से ऊपर के समान है का उपयोग कर सकते हैं।

/// <summary>Cancels the <see cref="T:System.Threading.CancellationTokenSource" /> after the specified duration.</summary> 
    /// <param name="source">The CancellationTokenSource.</param> 
    /// <param name="dueTime">The due time in milliseconds for the source to be canceled.</param> 
    public static void CancelAfter(this CancellationTokenSource source, int dueTime) 
    { 
    if (source == null) 
     throw new NullReferenceException(); 
    if (dueTime < -1) 
     throw new ArgumentOutOfRangeException("dueTime"); 
    Contract.EndContractBlock(); 
    Timer timer = (Timer) null; 
    timer = new Timer((TimerCallback) (state => 
    { 
     timer.Dispose(); 
     TimerManager.Remove(timer); 
     try 
     { 
     source.Cancel(); 
     } 
     catch (ObjectDisposedException ex) 
     { 
     } 
    }), (object) null, -1, -1); 
    TimerManager.Add(timer); 
    timer.Change(dueTime, -1); 
    } 
संबंधित मुद्दे