2013-05-29 16 views
20

क्या थ्रेड सुरक्षित है? ऐसा लगता है कि टास्क क्लास थ्रेड सुरक्षित है इसलिए मुझे लगता है कि यह भी थ्रेड सुरक्षित है, लेकिन मुझे कहीं भी पुष्टि नहीं मिली है। कस्टम प्रतीक्षाकर्ता के लिए थ्रेड सुरक्षा भी एक आवश्यकता है - मेरा मतलब IsCompleted, GetAwaiter, आदि विधियों के लिए है? अर्थात। यदि वे विधियां थ्रेड सुरक्षित नहीं हैं, तो थ्रेड सुरक्षित रहेंगे? हालांकि, मुझे जल्द ही कस्टम प्रतीक्षाकर्ता की आवश्यकता होने की उम्मीद नहीं है।क्या एकाधिक थ्रेड से एक ही कार्य का इंतजार करना ठीक है - थ्रेड सुरक्षित है?

उपयोगकर्ता परिदृश्य का एक उदाहरण:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Threading.Tasks; 

namespace scratch1 
{ 
    class Foo 
    { 
     Task<int> _task; 

     public Foo() 
     { 
      _task = Task.Run(async() => { await Task.Delay(5000); return 5; }); 
     } 

     // Called from multiple threads 
     public async Task<int> Bar(int i) 
     { 
      return (await _task) + i; 
     } 
    } 

    class Program 
    { 
     public static void Main(string[] args) 
     { 
      Foo foo = new Foo(); 

      List<Task> tasks = new List<Task>(); 
      foreach (var i in Enumerable.Range(0, 100)) 
      { 
       tasks.Add(Task.Run(async() => { Console.WriteLine(await foo.Bar(i)); })); 
      } 

      Task.WaitAll(tasks.ToArray()); 
     } 
    } 
} 

उत्तर

14

आप का संकेत के रूप में, await काफी पतली है कि यह नहीं करता है: मान लीजिए मैं एक पृष्ठभूमि कार्य जो एक परिणाम के अतुल्यकालिक रूप से देता है, जो फिर से अधिक थ्रेड से प्रयोग किया जाता है करते हैं पहली जगह धागे को नहीं देखते हैं।

await (राज्य मशीन के भीतर संकलक-जेनरेट कोड और बीसीएल में समर्थन वर्ग) से जुड़े कोड एक समय में केवल एक थ्रेड पर ही चलेंगे। (यह प्रतीक्षा करने योग्य से वापस आने पर एक अलग धागे पर स्विच कर सकता है, लेकिन पिछला रन पहले ही समाप्त हो चुका है)

वास्तविक थ्रेड-सुरक्षा उस ऑब्जेक्ट पर निर्भर करती है जिसकी आप प्रतीक्षा कर रहे हैं।
इसमें कॉलबैक जोड़ने के लिए एक थ्रेड-सुरक्षित तरीका होना चाहिए (या await इसे दो बार तोड़ना दो बार टूट सकता है)।

इसके अतिरिक्त, इसे कॉलबैक को बिल्कुल एक बार कॉल करना होगा, या यह राज्य मशीन को तोड़ सकता है। (विशेष रूप से, यदि यह एक ही समय में दो धागे पर कॉलबैक चलाता है, तो चीजें बहुत गलत हो जाएंगी)

Task थ्रेड-सुरक्षित है।

+5

आपका पहला कथन लोगों को यह सोचने में गुमराह कर सकता है कि 'प्रतीक्षा' मौलिक रूप से असुरक्षित है ... जबकि मुझे लगता है कि आपका मतलब है कि यह न तो स्वाभाविक रूप से सुरक्षित है और न ही असुरक्षित है - यह जो कुछ भी इंतजार कर रहा है, वह सिर्फ प्रतिनिधि है, और यदि यह 'कार्य' है, तो आप ' ठीक है –

+0

@ जोन्स स्केट: अच्छा बिंदु। क्या यह बेहतर है? – SLaks

+0

निश्चित रूप से, धन्यवाद। यद्यपि "केवल एक थ्रेड पर ही चलाया जाएगा" शायद "एक विधि में केवल एक थ्रेड पर चलना चाहिए, प्रति विधि आमंत्रण (जो राज्य मशीन के एक उदाहरण के अनुरूप है)"। यह निश्चित रूप से 'प्रतीक्षा' बिंदुओं पर धागे के बीच चारों ओर हॉप कर सकता है, लेकिन यह कई धागे पर एक साथ नहीं चलेंगे। (कम से कम तब तक जब तक आप इसे बहुत दुर्व्यवहार नहीं करते ... जो हमेशा मजेदार होता है।) –

संबंधित मुद्दे