दिलचस्प पोस्ट
मैं कैसे () के साथ देरी () का उपयोग कर सकते हैं शो () और छिपाने () में Jquery में क्या मैं एक ही कैच क्लॉज में कई जावा अपवादों को पकड़ सकता हूं? एकाधिक फ़ाइलों को पढ़ना और उपयोगकर्ता इनपुट के आधार पर गणना की गई गणना अनक्यूट टाइप एरर: अपरिभाषित संपत्ति का 'एमएसआई' पढ़ नहीं सकता कैसे जाओ में कई आदेश पाइप? एंड्रॉइड: फोकस, सक्षम, दबाए गए, और चुने हुए राज्यों के बीच अंतर क्या है? एंड्रॉइड: एक गतिविधि संदर्भ के बाहर WebView का उपयोग करना सिस्टम में कनवर्ट करें। ड्रॉइंग। Icon को System.Media.ImageSource JTextArea के केवल भागों में बोल्ड टेक्स्ट कैसे प्रदर्शित करें? विंडो के लिए सबसे हल्के वेब सर्वर (केवल स्थिर सामग्री) कोडिग्नर सक्रिय रिकॉर्ड में सम्मिलित क्वेरी के बाद अंतिम डालें आईडी कैसे प्राप्त करें शीर्ष पर और नीचे कार्रवाई आइटम के साथ एंड्रॉइड स्प्लिट एक्शन बार? क्या यह यूआरएल में एक से अधिक प्रश्न चिह्नों के लिए मान्य है? छवि कैसे आकर्षित करें छवि पर? PHP दिनांकटाइम माइक्रोसॉन्ड्स हमेशा 0 देता है

अग्रदूत पहचानकर्ता और समापन

दो निम्न स्निपेट्स में, क्या पहले एक सुरक्षित है या क्या आपको दूसरा वाला करना चाहिए?

सुरक्षित से मेरा मतलब है कि प्रत्येक थ्रेड फू पर विधि को कॉल करने के लिए गारंटी दी जाती है, जिसमें लूप इरेज़रेशन में थ्रेड बनाया गया था?

या क्या आपको लूप के प्रत्येक पुनरावृत्ति के लिए एक नया चर "स्थानीय" के संदर्भ की प्रतिलिपि बनाना चाहिए?

var threads = new List<Thread>(); foreach (Foo f in ListOfFoo) { Thread thread = new Thread(() => f.DoSomething()); threads.Add(thread); thread.Start(); } 

 var threads = new List<Thread>(); foreach (Foo f in ListOfFoo) { Foo f2 = f; Thread thread = new Thread(() => f2.DoSomething()); threads.Add(thread); thread.Start(); } 

अद्यतन: जैसा कि जॉन स्केट के जवाब में बताया गया है, इसमें थ्रेडिंग के साथ विशेष रूप से कुछ नहीं है।

Solutions Collecting From Web of "अग्रदूत पहचानकर्ता और समापन"

संपादित करें: यह सभी परिवर्तन सी # 5 में है, जहां परिवर्तनशील परिभाषित किया गया है (कंपाइलर की आंखों में)। सी # 5 से, वे वही हैं


दूसरा सुरक्षित है; पहले नहीं है

foreach साथ, चर को लूप के बाहर घोषित किया जाता है – यानी

 Foo f; while(iterator.MoveNext()) { f = iterator.Current; // do something with f } 

इसका मतलब है कि क्लोजर क्षेत्र की दृष्टि से केवल 1 f है, और थ्रेड्स बहुत ही भ्रमित हो सकते हैं – कुछ उदाहरणों पर विधि को कई बार बुलाते हैं और दूसरों पर बिल्कुल नहीं। आप लूप के अंदर एक दूसरे वैरिएबल घोषणा के साथ इसे ठीक कर सकते हैं:

 foreach(Foo f in ...) { Foo tmp = f; // do something with tmp } 

इसके बाद प्रत्येक क्लोजर दायरे में एक अलग tmp होता है, इसलिए इस समस्या का कोई जोखिम नहीं है।

यहां समस्या का एक साधारण प्रमाण है:

  static void Main() { int[] data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; foreach (int i in data) { new Thread(() => Console.WriteLine(i)).Start(); } Console.ReadLine(); } 

आउटपुट (यादृच्छिक पर):

 1 3 4 4 5 7 7 8 9 9 

एक अस्थायी चर जोड़ें और यह काम करता है:

  foreach (int i in data) { int j = i; new Thread(() => Console.WriteLine(j)).Start(); } 

(प्रत्येक नंबर एक बार, लेकिन निश्चित तौर पर ऑर्डर की गारंटी नहीं है)

पॉप कैटलिन और मार्क ग्रेवेल के उत्तर सही हैं। मैं जो जोड़ना चाहता हूं, वह मेरे क्लोजर के बारे में एक लेख है (जो जावा और सी # दोनों के बारे में बात करता है) बस सोचा कि यह मूल्य का थोड़ा जोड़ सकता है

संपादित करें: मुझे लगता है कि यह एक उदाहरण देने के लायक है, जिसमें सूत्रण की अनिश्चितता नहीं है। यहां एक छोटा लेकिन पूरा कार्यक्रम दोनों दृष्टिकोण दिखा रहा है "खराब कार्यवाही" सूची 10 बार दस बार प्रिंट करती है; "अच्छी कार्रवाई" सूची में 0 से 9 तक की गणना है

 using System; using System.Collections.Generic; class Test { static void Main() { List<Action> badActions = new List<Action>(); List<Action> goodActions = new List<Action>(); for (int i=0; i < 10; i++) { int copy = i; badActions.Add(() => Console.WriteLine(i)); goodActions.Add(() => Console.WriteLine(copy)); } Console.WriteLine("Bad actions:"); foreach (Action action in badActions) { action(); } Console.WriteLine("Good actions:"); foreach (Action action in goodActions) { action(); } } } 

विकल्प 2 का उपयोग करने की आवश्यकता, बदलते चर के आस-पास एक क्लॉज बनाने से वेरिएबल के मान का उपयोग किया जाएगा, जब चर का उपयोग किया जाता है और क्लोजर सृजन समय पर नहीं।

सी # में गुमनाम तरीकों के कार्यान्वयन और इसके परिणाम (भाग 1)

सी # और उसके परिणाम (भाग 2) में अनाम तरीकों का कार्यान्वयन

सी # और उसके परिणाम (भाग 3) में अनाम तरीकों का कार्यान्वयन

संपादित करें: इसे स्पष्ट करने के लिए, सी # बंद में " लेक्सिकल क्लोजर " हैं, जिसका अर्थ है कि वे एक वैरिएबल का मान नहीं लेते हैं, लेकिन वे चर स्वयं भी। इसका मतलब है कि जब एक बदलते हुए परिवर्तनीय को बंद कर दिया जाता है, तो वास्तव में बंद करने के संदर्भ में वेरिएबल का कोई संदर्भ नहीं होता है, जो इसके मूल्य की प्रति नहीं होती है।

Edit2: सभी ब्लॉग पोस्ट के लिंक जोड़े गए हैं, अगर कोई भी कंपाइलर इंटरनल के बारे में पढ़ने में रुचि रखता है

यह एक दिलचस्प सवाल है और ऐसा लगता है जैसे हमने लोगों को सभी विभिन्न तरीकों से जवाब दिया है। मैं इस धारणा के तहत था कि दूसरा रास्ता एकमात्र सुरक्षित तरीका होगा। मैं एक असली त्वरित सबूत मार दिया:

 class Foo { private int _id; public Foo(int id) { _id = id; } public void DoSomething() { Console.WriteLine(string.Format("Thread: {0} Id: {1}", Thread.CurrentThread.ManagedThreadId, this._id)); } } class Program { static void Main(string[] args) { var ListOfFoo = new List<Foo>(); ListOfFoo.Add(new Foo(1)); ListOfFoo.Add(new Foo(2)); ListOfFoo.Add(new Foo(3)); ListOfFoo.Add(new Foo(4)); var threads = new List<Thread>(); foreach (Foo f in ListOfFoo) { Thread thread = new Thread(() => f.DoSomething()); threads.Add(thread); thread.Start(); } } } 

यदि आप इसे चलाते हैं तो आपको 1 विकल्प निश्चित रूप से सुरक्षित नहीं दिखाई देगा।

आपके मामले में, आप अपने ListOfFoo को थ्रेड्स के अनुक्रम में मैप करके नकल की चाल का उपयोग किए बिना समस्या से बच सकते हैं:

 var threads = ListOfFoo.Select(foo => new Thread(() => foo.DoSomething())); foreach (var t in threads) { t.Start(); } 

दोनों सी # संस्करण 5 (। NET फ्रेमवर्क 4.5) के रूप में सुरक्षित हैं। विवरण के लिए इस प्रश्न को देखें: क्या फॉरचाच का उपयोग सी # 5 में बदल दिया गया है?

 Foo f2 = f; 

उसी संदर्भ के रूप में बताता है

 f 

तो कुछ भी नहीं खो गया और कुछ भी नहीं मिला …