2013-07-15 6 views
6

मैंने एरिक लिपर्ट के article को लगभग async पढ़ा है, और भ्रम के बारे में लोगों के पास async कीवर्ड था। उन्होंने कहा:async - वर्तमान धागे पर रहें?

यह (async) का अर्थ है "इस विधि नियंत्रण प्रवाह शामिल है कि अतुल्यकालिक संचालन का इंतजार कर रहा है और इसलिए शैली गुजर सुनिश्चित करना है कि अतुल्यकालिक संचालन इस विधि को फिर से शुरू कर सकते हैं निरंतरता में संकलक द्वारा फिर से लिखा हो जाएंगे सही जगह पर। "async तरीकों इसके बारे में पूरी बात यह है कि आप के रूप में ज्यादा संभव

मुझे यह समझ में नहीं आता के रूप में वर्तमान धागे पर रहते हैं। यदि मैं एक एसिंक्रोनस विधि (Task) निष्पादित करता हूं और यह चलता है, तो यह निश्चित रूप से किसी अन्य थ्रेड पर चलता है।

इसके अलावा, अगर मैं लिखना एक विधि await, (imho) का उपयोग करता है यह सामान्य नियंत्रण प्रवाह जारी करता है, और कोड पुनर्संशोधित एक जैसे "ContinueWith" बाद में, एक और धागे पर है।

मैं (कंसोल) के साथ यह परीक्षण किया:

/*1*/ public void StartChain() 
/*2*/ { 
/*3*/   var a = FuncA(); 
/*4*/   Console.WriteLine(a.Result); 
/*5*/ } 
/*6*/ 
/*7*/ public async Task <int> FuncA() 
/*8*/ { 
/*9*/   Console.WriteLine("A--" + Thread.CurrentThread.ManagedThreadId); 
/*10*/   var t = await FuncB(); 
/*11*/   Console.WriteLine("B--" + Thread.CurrentThread.ManagedThreadId); 
/*12*/   return t; 
/*13*/ } 
/*14*/ 
/*15*/ public async Task <int> FuncB() 
/*16*/ { 
/*17*/   Console.WriteLine("C--" + Thread.CurrentThread.ManagedThreadId); 
/*18*/   await Task.Delay(2000); 
/*19*/   Console.WriteLine("D--" + Thread.CurrentThread.ManagedThreadId); 
/*20*/   return 999; 
/*21*/ } 
/*22*/ 
/*23*/ void Main() 
/*24*/ { 
/*25*/   StartChain(); 
/*26*/ } 
/*27*/ 

परिणाम है:

A--7 
C--7 
D--17   <-----D and B are on different thread 
B--17 
999 

तो क्या एरिक कहा, "वर्तमान धागा पर रहने" द्वारा मतलब था?

संपादित करें 1:

asp.net में यह भी लौट differnt धागा आईडी।

public async Task<int> FuncA() 
{ 
    Response.Write("<br/>C----" + Thread.CurrentThread.ManagedThreadId); 
    var t = await FuncB(); 
    Response.Write("<br/>D----" + Thread.CurrentThread.ManagedThreadId); 
    return t; 
} 

public async Task<int> FuncB() 
{ 
    Response.Write("<br/>E----" + Thread.CurrentThread.ManagedThreadId); 
    await Task.Delay(2000); 
    Response.Write("<br/>F----" + Thread.CurrentThread.ManagedThreadId); 
    return 999; 
} 



protected async void Page_Load(object sender, EventArgs e) 
{ 
    Response.Write("<br/>A----" + Thread.CurrentThread.ManagedThreadId); 
    var a=await FuncA(); 
    Response.Write("<br/>B----" + Thread.CurrentThread.ManagedThreadId); 

} 

A----8 
C----8 
E----8 
F----9 
D----9 
B----9 

संपादित यह है कि धागा लगता है 2

(एक जवाब मिलने के बाद ही)

केवल जीयूआई क्षुधा में परोसा जाता है। मैं WinForm पर

public async Task<int> FuncA() 
     { 
      textBox1.Text +=Environment.NewLine+ "\nC----" + Thread.CurrentThread.ManagedThreadId; 
      var t = await FuncB(); 
      textBox1.Text += Environment.NewLine + "\nD----" + Thread.CurrentThread.ManagedThreadId; 
      return t; 
     } 

     public async Task<int> FuncB() 
     { 
      textBox1.Text += Environment.NewLine + "\nE----" + Thread.CurrentThread.ManagedThreadId; 
      await Task.Delay(2000); 
      textBox1.Text += Environment.NewLine + "\nF----" + Thread.CurrentThread.ManagedThreadId; 
      return 999; 
     } 




     private async void Form1_Load(object sender, EventArgs e) 
     { 
      textBox1.Text += Environment.NewLine + "\nA----" + Thread.CurrentThread.ManagedThreadId; 
      var a = await FuncA(); 
      textBox1.Text += Environment.NewLine + "\nB----" + Thread.CurrentThread.ManagedThreadId; 
     } 

enter image description here

+0

इस लेख से लिंक करें जिसे आप –

+0

@downvoter के बारे में उलझन में हैं - टिप्पणी उपयोगी होगी। –

+1

जिस कार्य का आप इंतजार कर रहे हैं वह दूसरे धागे पर चलता है। Async विधि में अन्य सभी कोड मूल धागे पर चलता है। इंतजार एक नया काम शुरू नहीं करता है। यह मूल धागे में जारी है एक समतुल्य है। ऐसे कई ब्लॉग हैं जो इस पर चर्चा करते हैं। –

उत्तर

9

एसिंक/प्रतीक्षा समर्थन प्रोग्रामर को जीयूआई लिखने में मदद करने के लिए जोड़ा गया था जो जमा नहीं होता है।स्टोर ऐप्स में विशेष रूप से उपयोगी, और मुख्य कारण यह सी # v5 में जोड़ा गया था, WinRT एक सुंदर असभ्य एपीआई है जिसमें कई असीमित तरीके हैं।

"उसी धागे पर रहें" परिदृश्य बहुत एक जीयूआई ऐप में महत्वपूर्ण है, क्योंकि एक जीयूआई थ्रेड-सुरक्षित नहीं है। हालांकि इसे एक संदेश लूप की आवश्यकता होती है, उसी थ्रेड पर फिर से शुरू करने के लिए एसिंक्रोनस कोड प्राप्त करने का एकमात्र तरीका। संदेश लूप producer-consumer problem का मुख्य समाधान है। स्पष्ट रूप से आपके प्रोग्राम में कोई नहीं है, कंसोल मोड ऐप की तरह दिखता है। इसलिए आपको यह व्यवहार नहीं मिलता है, यह एक कार्यकर्ता थ्रेड पर फिर से शुरू होता है।

कोई समस्या नहीं है, आप वास्तव में की आवश्यकता नहीं है क्योंकि यह एक ही थ्रेड पर फिर से शुरू होता है क्योंकि कंसोल थ्रेड-सुरक्षित है। खैर, ज्यादातर, जब आप इनपुट मांगते हैं तो .NET 4.5 में जो लॉक जोड़ा गया था उसे गिनती नहीं। निश्चित रूप से इसका भी अर्थ है कि आपके पास async/await के लिए उपयोग की एक हेकोफ्लोट नहीं है, एक कार्य ठीक काम करता है।

+0

थोड़ा ओटी, लेकिन मैं थोड़ी देर पहले उस विचित्र बल-इनपुट-टू-सिंक्रोनस व्यवहार में ठोकर खाई। क्या आप जानते हैं कि उन्होंने ऐसा क्यों किया? –

+1

कोई विचार नहीं। इसके पीछे एक बड़ी योजना थी, उसी लॉक को सीआरटी में भी जोड़ा गया था। प्रोग्रामर का एक * बहुत * है जो परीक्षण कार्यक्रमों को जारी रखने के लिए किसी भी कुंजी को "जारी रखने के लिए किसी भी कुंजी को दबाएं" पर नर्सिंग डेडलॉक कर रहे हैं, यह लॉक एक गलती थी। –

+1

और इसे हटाकर तय किया गया था। –

10

एरिक Lippert के "सूत्र" शब्दावली सरल है इस कोड को चलाते हैं। मेरे ब्लॉग पर मेरे पास async/await intro है जो बताता है कि await वर्तमान संदर्भ को कैप्चर करेगा और async विधि को फिर से शुरू करने के लिए इसका उपयोग करेगा।

यदि आप यूआई संदर्भ में हैं, तो संदर्भ एकल यूआई थ्रेड है, और async विधि उस थ्रेड पर फिर से शुरू हो जाएगी। अन्यथा, नियम थोड़ा अधिक जटिल हैं। विशेष रूप से, कंसोल ऐप्स थ्रेड पूल पर डिफ़ॉल्ट पुन: प्रारंभ करके async विधियों को कोई संदर्भ प्रदान नहीं करते हैं।

+0

ive आपके लेख को कई बार पढ़ें। (मेरे अंतिम एसिंक प्रश्न देखें;) –

+0

फिर भी लेख इस प्रश्न का उत्तर देता है। :) फिर से 'सिंक्रनाइज़ेशन कॉन्टेक्स्ट' और' टास्कशेड्यूलर 'के बारे में अनुभाग पढ़ें। –

+0

तो यह थ्रेड नहीं है जो रखा जाता है। (मेरा वास्तविक प्रश्न - उत्तर देने के लिए धन्यवाद) - लेकिन संदर्भ (जो पहले से ही मुझे ज्ञात है।) ...? कृपया –

19

यदि मैं एक एसिंक्रोनस विधि निष्पादित करता हूं और यह चलता है, तो यह निश्चित रूप से किसी अन्य धागे पर चलता है।

नहीं, यह आमतौर पर किसी अन्य धागे पर चलता है। यह निश्चित रूप से किसी अन्य धागे पर नहीं चलता है।

एक पल के लिए धागे के बारे में सोचना बंद करें और एसिंक्रोनि की प्रकृति के बारे में सोचें। एसिंक्रोनि की प्रकृति है:

  • मुझे कुछ वर्कफ़्लो मिला है जो मैं वर्तमान में निष्पादित कर रहा हूं।
  • मैं इस कार्यप्रवाह में आगे नहीं बढ़ सकता जब तक मैं जानकारी एक्स मिल
  • मैं जब तक मैं भविष्य में कुछ बिंदु पर जानकारी एक्स
  • मिलता है, एक बार मैं एक्स है कुछ और करने जा रहा हूँ, मैं मैं वापस लौटने जा रहा हूं जहां मैंने अपने वर्कफ़्लो में छोड़ा और जारी रखा।

मान लीजिए कि आप अपने कर कर रहे हैं और इस जटिल वर्कफ़्लो के बीच में आपके पास प्रदर्शन करने के लिए एक बड़ा जोड़ा है। आप कुछ ऑपरेशन कर सकते हैं तो याद रखें कि आप कहां हैं, और दोपहर का भोजन करें। फिर वापस आएं और कुछ और ऑपरेशन करें, फिर याद रखें कि आप कहां हैं, और बिल्ली को खिलाएं। फिर वापस आएं और कुछ और ऑपरेशन करें, फिर याद रखें कि आप कहां हैं, और व्यंजन धोएं। फिर गणना को समाप्त करें, और फिर से शुरू करें जहां आपने अपने वर्कफ़्लो में छोड़ा था।

यह एक असीमित गणना है लेकिन इसे केवल एक कार्यकर्ता को ऐसा करने की आवश्यकता है। कई श्रमिक होने के नाते एसिंक्रोनि करने का एक विशेष रूप से सुविधाजनक तरीका है, यह एक आवश्यकता नहीं है।

+0

एरिक, लेकिन अगर मैंने अपनी गणना छोड़ी और बिल्ली को खिलाया - गणना ऑपरेशन (जो मैं पेंसिल और पेपर के साथ करता हूं) अवरुद्ध है - जब तक मैं वापस आऊंगा .... तो यह तुल्यकालिक ऑपरेशन के रूप में लगता है। कृप्या मुझे सही करें। –

+4

यह असीमित ऑपरेशन नहीं है। लंबी गणना करना एसिंक्रोनस ऑपरेशन है क्योंकि आप इसके दौरान अन्य काम करने से अवरुद्ध नहीं हैं। –

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