2013-01-17 8 views
8

मैंने सी # 5 और नेट 4.5 में असीमित प्रोग्रामिंग सीखना शुरू किया और ऐसा कुछ है जो मुझे समझ में नहीं आता है।एसिंक्रोनस प्रोग्रामिंग और लूप में प्रतीक्षा करें

private static int count; 

public static void Main() 
{ 
    LoopTest(); 

    Console.ReadKey(false); 
} 

static async void LoopTest() 
{ 
    count = 0; 

    for (var index = 0; index < 10; ++index) 
    { 
     Console.WriteLine("({0}) In Loop before await, Index {1}, Thread: {2}", count++, index, Thread.CurrentThread.ManagedThreadId); 
     await Task.Factory.StartNew(() => Thread.Sleep(10)); 
    } 
} 

परिणाम है:

(0) In Loop before await, Index 0, Thread: 9 
(1) In Loop before await, Index 1, Thread: 10  
(2) In Loop before await, Index 2, Thread: 11 
(3) In Loop before await, Index 3, Thread: 10 
(4) In Loop before await, Index 4, Thread: 11 
(5) In Loop before await, Index 5, Thread: 10 
(6) In Loop before await, Index 6, Thread: 12 
(7) In Loop before await, Index 7, Thread: 11 
(8) In Loop before await, Index 8, Thread: 10 
(9) In Loop before await, Index 9, Thread: 12 

तो वहाँ अलग अलग ही पाश तक पहुँचने धागे कर रहे हैं? इंडेक्स वैरिएबल पर रेस-कंडीशन है?

+0

कृपया प्रतीक्षा करें टास्क.फैक्टरी.स्टार्टन्यू (() => थ्रेड। स्लीप (10)); कार्य का इंतजार कर रहे हैं। डेले (10)। आपको अपने धागे को 10 एमएस के लिए जाने देना है, इसे पकड़ना नहीं है। –

+0

@publicENEMY तो 'कार्य। डेले' करता है;) –

+2

@ टोनीपेट्रिना थ्रेड। 10 मीटर धागे के उपयोग को अनुकरण करने के लिए नींद को पकड़ने के लिए उपयोग किया जाता है। –

उत्तर

13

नहीं, कोई दौड़ की स्थिति नहीं है। आप एक नया कार्य शुरू करते हैं, जो पृष्ठभूमि में चलाएगा, लेकिन आपका कोड तब तक जारी नहीं रहेगा जब तक कि कार्य समाप्त न हो जाए, ताकि आप सुनिश्चित हो सकें कि आपका कोड केवल एक ही थ्रेड में किसी भी समय निष्पादित किया जाएगा।

हालांकि, क्योंकि यह एक कंसोल एप्लिकेशन है, वर्तमान में कोई SyncronizationContext नहीं है। (एक विनफॉर्म, डब्ल्यूपीएफ, एएसपी, सिल्वरलाइट इत्यादि के विपरीत, जिसमें आवेदन होगा।) इसका मतलब है कि किसी भी await कॉल की निरंतरता थ्रेड पूल में चलती है, कॉलिंग थ्रेड में नहीं। तो हाँ, आप लूप के प्रत्येक पुनरावृत्ति में थ्रेड पूल थ्रेड में से एक में चल रहे हैं, और यह हर बार एक अलग हो सकता है, लेकिन आप यह सुनिश्चित कर सकते हैं कि, जो भी आपने नए कार्य के अंदर रखा है उसे छोड़कर, आप " समाप्त करें "आप अगली बार काम करना शुरू करने से पहले किसी दिए गए धागे पर चल रहे हैं, जो सुनिश्चित करता है कि किसी भी समय केवल एक थ्रेड चलने वाला कोड है (जिसका मतलब कोई दौड़ की स्थिति नहीं है)।

+0

आपके उत्तर के लिए धन्यवाद! मै समझता हुँ :) – m1o2

4

तुम क्या कर रहे हैं यह एक कार्य बनाता है और फिर उस कार्य को पूरा करने के लिए इंतजार कर रहा है वास्तव में asycnhronous

await Task.Factory.StartNew(() => Thread.Sleep(10)); 

नहीं है। आप बस थ्रेड को भी कॉल कर सकते हैं। नींद (10) यहां।

इस होगा करने के लिए एक और अधिक उपयुक्त तरीका:

Task myTask = Task.Factory.StartNew(() => Thread.Sleep(10)); 
... do stuff here ... 
await myTask; // Now wait for the task to complete 

आप एक पाश में कार्य करने के क्या करना चाहते हैं, तो आप Parallel.Foreach() विधि पर गौर करना चाहिए।

+0

आपके उत्तर के लिए धन्यवाद! लेकिन मेरे पास कुछ प्रश्न हैं। यदि मैं वर्तमान थ्रेड पर कोई कार्य बना रहा हूं तो बाकी धागे कौन बना रहा है? या क्यों प्रबंधित थ्रेड आईडी बदल रहा है? – m1o2

+7

उदाहरण सिर्फ एक खिलौना उदाहरण है जिसमें वह प्रयोग कर रहा है और परिणामों को समझाने की कोशिश कर रहा है। यह उन परिणामों की व्याख्या नहीं करता है, और यह कहने का प्रयास कर रहा है कि परीक्षण गलत है, जब कुछ भी नहीं है, यह समझने के लिए पूरा करने की कोशिश कर रहा है कि 'प्रतीक्षा करें' कैसे काम करता है। – Servy

+0

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

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