2013-10-27 3 views
7

Azure संग्रहण ग्राहक पुस्तकालय 2.1, मैं टेबल भंडारण async के एक प्रश्न बनाने पर काम कर रहा हूँ के साथ कार्य करना साथ Table.ExecuteQuerySegmentedAsync() का उपयोग कैसे करें।Azure तालिका भंडारण

public async Task<List<TAzureTableEntity>> GetByPartitionKey(string partitionKey) 
{ 
    var theQuery = _table.CreateQuery<TAzureTableEntity>() 
         .Where(tEnt => tEnt.PartitionKey == partitionKey); 
    TableQuerySegment<TAzureTableEntity> querySegment = null; 
    var returnList = new List<TAzureTableEntity>(); 
    while(querySegment == null || querySegment.ContinuationToken != null) 
    { 
     querySegment = await theQuery.AsTableQuery() 
            .ExecuteSegmentedAsync(querySegment != null ? 
             querySegment.ContinuationToken : null); 
     returnList.AddRange(querySegment); 
    } 
    return returnList; 
} 

मान वापस आ रहा तो वहाँ तालिका भंडारण के लिए दौर यात्राएं का एक बहुत हो जाएगा डेटा के एक बड़े सेट है चलो: मैं इस कोड बनाया। समस्या मेरे पास है कि हम डेटा का एक सेट का इंतजार कर रहे हैं, एक में स्मृति सूची में जोड़कर, अधिक डेटा का इंतजार कर, एक ही सूची में जोड़कर, अभी तक अधिक डेटा का इंतजार कर, सूची में जोड़कर ... और इसलिए है आगे और आगे। क्यों न केवल एक नियमित tableQuery के आसपास एक कार्य। फैक्टरी। स्टार्टन्यू() लपेटें? इसलिए जैसा: इस तरह से

public async Task<List<TAzureTableEntity>> GetByPartitionKey(string partitionKey) 
{ 
    var returnList = await Task.Factory.StartNew(() => 
               table.CreateQuery<TAzureTableEntity>() 
               .Where(ent => ent.PartitionKey == partitionKey) 
               .ToList()); 
    return returnList; 
} 

कर रहा है कि हम SynchronizationContext आगे पीछे इतना उछल नहीं कर रहे हैं लगता है। या यह वास्तव में कोई फर्क पड़ता है?

संपादित प्रश्न

ऊपर उल्लेख किया दो स्थितियों में क्या अंतर है इस प्रकार संशोधित करने के लिए?

+1

आप अपने आप async विधि में अपने "खंड" रख दिया और का उपयोग कर इसे कहते ConfigureAwait (गलत)। –

+0

@PauloMorgado - विडंबना यह है कि वास्तव में मेरे पास TableQuerySegement है और जबकि पहले से ही एक अलग विधि में कथन है, लेकिन मुझे कार्य पर ConfigureAwait (false) विधि के बारे में पता नहीं था। पारितोषिक के लिए धन्यवाद! – Hallmanac

+2

सभी लाइब्रेरी कोड के लिए ConfigureAwait (false) की अनुशंसा की जाती है और मैं इसे सभी गैर-यूआई एप्लिकेशन कोड में विस्तारित करूंगा। –

उत्तर

6

दोनों के बीच का अंतर यह है कि आपका दूसरा संस्करण पूरे समय क्वेरी को निष्पादित करने के लिए ThreadPool धागा को अवरुद्ध कर देगा। यह एक जीयूआई एप्लिकेशन में स्वीकार्य हो सकता है (जहां आप चाहते हैं कि यूआई थ्रेड के अलावा कहीं भी कोड निष्पादित करना है), लेकिन यह सर्वर अनुप्रयोग में async के किसी स्केलेबिलिटी फायदे को अस्वीकार कर देगा।

इसके अलावा, आप अपने पहले संस्करण प्रत्येक गोल यात्रा के लिए यूआई संदर्भ पर वापस (जो एक उचित आवश्यकता है), तो ConfigureAwait(false) का उपयोग जब भी आप await का उपयोग नहीं करना चाहते हैं:

querySegment = await theQuery.AsTableQuery() 
          .ExecuteSegmentedAsync(…) 
          .ConfigureAwait(false); 

इस तरह, पहले के बाद सभी पुनरावृत्तियों (सबसे अधिक संभावना) ThreadPool धागे पर निष्पादित होंगे और यूआई संदर्भ पर नहीं।

Btw, अपने दूसरे संस्करण में, आप वास्तव में await बिल्कुल जरूरत नहीं है, तो आप सिर्फ सीधे लौट सकते हैं Task:

public Task<List<TAzureTableEntity>> GetByPartitionKey(string partitionKey) 
{ 
    return Task.Run(() => table.CreateQuery<TAzureTableEntity>() 
           .Where(ent => ent.PartitionKey == partitionKey) 
           .ToList()); 
} 
+0

एसिंक के स्केलेबिलिटी फायदे क्वेरी (सेगमेंट) (क्वेरी का नकारात्मक) सहायता (नकारात्मक संस्करण) की सहायता कैसे करता है? सभी चीजें बराबर होती हैं आप अभी भी 'थ्रेडपूल' थ्रेड पर कब्जा कर रहे हैं। विशेष रूप से 'ConfigureAwait (false)' का उपयोग करते समय। क्या मैं सही ढंग से सोच रहा हूँ? – Hallmanac

+1

@ हेलमैनैक नहीं, यह गलत है। 'प्रतीक्षा' का मुद्दा यह है कि जब एसिंक्रोनस ऑपरेशन निष्पादित होता है, तो आप * किसी भी धागे पर कब्जा नहीं कर रहे हैं। 'ConfigureAwait (false)' के साथ, आप अगले सेगमेंट को शुरू करने के लिए केवल सेगमेंट के बीच थोड़े समय के लिए 'थ्रेडपूल' थ्रेड का उपयोग कर रहे हैं। – svick

+2

गोचा। यह नहीं पता था कि डेटा के साथ वापस आने के लिए 'क्वेरी सेगमेंट' की प्रतीक्षा करते समय यह 'थ्रेडपूल' थ्रेड पर कब्जा नहीं कर रहा था। विडंबना यह है कि, आपकी पिछली टिप्पणी पर गहरी खुदाई करते हुए मुझे इस विषय पर एक और अच्छा जवाब मिला। :-) यहां लिंक है जब दूसरों को यह उतना उपयोगी लगता है जितना मैंने किया था। http://stackoverflow.com/a/14898584/350312 – Hallmanac

2

अगर यह जवाब आप के लिए देख रहे हैं लेकिन मैं अभी भी यह उल्लेख करना चाहते हैं :) सुनिश्चित नहीं हैं।

जैसा कि आप पहले ही जानते हैं, दूसरी विधि (Task का उपयोग करके) आंतरिक रूप से निरंतर टोकन को संभालती है और सभी इकाइयों को प्राप्त करने के तरीके से बाहर आती है जबकि पहली विधि इकाइयों का एक समूह प्राप्त करती है (अधिकतम 1000 तक) और फिर आपको परिणाम सेट के साथ-साथ निरंतर टोकन भी देता है।

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

के आप एक वेब अनुप्रयोग जो एक मेज से डेटा से पता चलता बना रहे मान लेते हैं। इसके अलावा मान लेते हैं कि मेज संस्थाओं की संख्या में हों जाने (के 100000 संस्थाओं मान लीजिए)। पहली विधि का उपयोग करके, आप केवल 1000 इकाइयों को परिणाम वापस उपयोगकर्ता को वापस कर सकते हैं और यदि उपयोगकर्ता चाहता है, तो आप 1000 इकाइयों के अगले सेट को ला सकते हैं और उन्हें उपयोगकर्ता को दिखा सकते हैं। जब तक उपयोगकर्ता चाहता है तब तक आप ऐसा करना जारी रख सकते हैं और तालिका में डेटा है। 2 विधि के साथ उपयोगकर्ता प्रतीक्षा करने के लिए जब तक सभी 100000 संस्थाओं मेज से लाई जाती हैं, के लिए होगा।

+0

यही कारण है कि मैं इसके बारे में सोच रहा था। अगर मैं एक वास्तविक आईनेमरेबल लौटने के लिए विधि को चाल/मजबूर करना चाहता था तो मैं async/await के लाभों को अस्वीकार करता हूं। यद्यपि आपके अंकन के उपयोग के मामले ने मुझे थोड़ा सोचा। आपको उपभोक्ता को निरंतरता टोकन उत्तीर्ण करना होगा ताकि वे इसे छोड़ने के लिए इसे वापस भंडार में पास कर सकें। इस संदर्भ में एसिंक के लिए यह एक अच्छा उपयोग केस होगा। – Hallmanac

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