2012-11-27 20 views
7

मैं पृष्ठभूमि में कोई काम करने का एक आसान तरीका ढूंढ रहा हूं, फिर पूरा होने पर कुछ (मुख्य धागे पर) अपडेट करें। यह निम्न स्तर के 'मॉडल' वर्ग में है, इसलिए मैं InvokeOnMainThread को कॉल नहीं कर सकता क्योंकि मेरे पास एनएसओब्जेक्ट नहीं है।सी # सरल पृष्ठभूमि धागा

public void GetItemsAsync(Action<Item[]> handleResult) 
{ 
    Item[] items=null; 
    Task task=Task.Factory.StartNew(() => 
    { 
    items=this.CreateItems(); // May take a second or two 
    }); 
    task.ContinueWith(delegate 
    { 
    handleResult(items); 
    }, TaskScheduler.FromCurrentSynchronizationContext()); 
} 

यह ठीक से काम करने लगता है, लेकिन

1) यह सबसे अच्छा (सरल) तरीका है: मैं इस विधि है?

2) मैं स्थानीय चर बारे में चिंतित हूँ:

Item{} items=null 

क्या है कि गायब जब विधि रिटर्न से पहले पृष्ठभूमि धागा पूरा करता है बंद हो जाता है?

धन्यवाद।

उत्तर

2

मैं अपने विधि थोड़ा एक Single Responsibility Principle का उल्लंघन करता है, क्योंकि यह बहुत ज्यादा कर रही है लगता है

+0

धन्यवाद, सिद्धांत रूप में बेहतर है। कार्य चर yourClass.CreateItems (टोकन) को भी हटा सकते हैं। (टी => { }, TaskScheduler.FromCurrentSynchronizationContext()); दयालुता हमें "टास्कशेड्यूलर.प्रॉमकंटेंट सिंक्रनाइज़ेशन कॉन्टेक्स्ट()" की आवश्यकता है। मैं ग्राहक के लिए सरल संभव एपीआई चाहते हैं तो इसके लिए या तो: 1) yourClass.GetItemsAsync (प्रतिनिधि (मद [] आइटम) {\t // आइटम के साथ कुछ करो}); या 2) yourClass.CreateItems (।) ContinueWith (टी => { // t.Result साथ कुछ करो}, TaskScheduler.FromCurrentSynchronizationContext()); तो मुझे अभी भी GetItemsAsync विधि वास्तव में चाहिए। – Bbx

+0

हाँ, आप सही हैं। लेकिन OO सिद्धांतों और कार्य-आधारित प्रोग्रामिंग के संदर्भ में GetItemsAsync पिछले समाधान की तुलना में अधिक स्पष्ट है। उदाहरण के लिए, प्रस्तावित तकनीक का उपयोग करना सी # 5.0 की प्रतीक्षा/एसिंक सुविधाओं का इंतजार करना बहुत आसान होगा। ओओपी के मामले में यह समाधान अधिक सरल है क्योंकि यह पहिया का आविष्कार करने की कोशिश नहीं कर रहा है। और एक टेस्टेबिलिटी को न भूलें: इस मामले में आप आसानी से इस कार्य को नकली कार्यान्वयन से प्राप्त कर सकते हैं और क्लाइंट कोड के किसी कोने केस का परीक्षण कर सकते हैं। –

1

आपका कोड ठीक दिखता है।

यदि आप सी # 5 का उपयोग कर सकते हैं तो यह async/await का उपयोग करने का एक आदर्श उदाहरण है, लेकिन यदि नहीं, तो आपको इसे लिखना होगा जैसा आपने निरंतरता के साथ किया है।

items चर आपके लैम्बडा में कब्जा कर लिया गया है, तो यह भी ठीक है।

जब आप एक बाहरी चर का उपयोग करते हुए एक लैम्ब्डा लिखते हैं, तो सी # कंपाइलर एक वर्ग बनाता है जिसमें चर शामिल होता है। इसे बंद करने के लिए कहा जाता है और इसका मतलब है कि आप अपने लैम्ब्डा के अंदर चर का उपयोग कर सकते हैं।

public void GetItemsAsync(Action<Item[]> handleResult) 
    { 
     var task = Task.Factory.StartNew<Item[]>(() => 
     { 
      return this.CreateItems(); // May take a second or two 
     }); 

     task.ContinueWith(delegate 
     { 
      handleResult(task.Result); 
     }, TaskScheduler.FromCurrentSynchronizationContext()); 
    } 
+0

तेज़ उत्तर के लिए धन्यवाद :) डेटा ट्रैफ़िक को पूरी तरह से अनदेखा करने के लिए आईओएस एपीआई के बारे में मेरे आखिरी प्रश्न के बाद मैं लगभग एसओ को छोड़ दूंगा। मुझे लगता है कि यह कुछ चीजों के लिए अच्छा है, न कि दूसरों के लिए। – Bbx

1

यहाँ एक अच्छे soultion है।

सब मैं CreateItems बदलने के लिए सुझाव है कि सबसे पहले Task वापस जाने के लिए बजाय GetItemsAsync में यह लपेटकर की:

public Task<Item[]> CreateItems(CancellationToken token) 
{ 
    return Task.Factory.StartNew(() => 
    // obtaining the data... 
    {}); 
} 

CancellationToken वैकल्पिक है, लेकिन अगर आप इस लंबे चल कार्रवाई को रद्द करने के लिए सक्षम आप कर सकते हैं।

इस पद्धति से

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

// Somewhere in the client of your class 
var task = yourClass.CreateItems(token); 
task.ContinueWith(t => 
// Code of the delegate that previously 
// passed to GetItemsAsync method 
{}, TaskScheduler.FromCurrentSynchronizationContext()); 

इस दृष्टिकोण का उपयोग आप केवल एक जिम्मेदारी के साथ और अधिक स्पष्ट कोड मिलेगा। Task कक्षा स्वयं first class object के रूप में एसिंक्रोनस ऑपरेशन का प्रतिनिधित्व करने के लिए एक आदर्श उपकरण है। प्रस्तावित तकनीक का उपयोग करके आप अपने क्लाइंट कोड को बदले बिना यूनिट परीक्षण के लिए नकली व्यवहार के साथ वर्तमान कार्यान्वयन को आसानी से नकल कर सकते हैं।

+0

धन्यवाद, यह अच्छा है :) – Bbx

+0

@Bbx: आपके पास परिणाम सुविधा नहीं है क्योंकि आपको कोड को बदलना चाहिए: कार्य कार्य = कार्य। फैक्टरी .... –

+0

धन्यवाद, हाँ मुझे अभी एहसास हुआ कि मैंने अपनी टिप्पणी पोस्ट करने के बाद :) – Bbx

2

कुछ इस तरह::

public void GetItemsAsync(Action<Item[]> handleResult) 
    { 
     int Id = 11; 
     Task<Item[]> task = Task.Factory.StartNew(() => CreateItems(Id)); // May take a second or two 
     task.ContinueWith(t => handleResult(t.Result), TaskScheduler.FromCurrentSynchronizationContext()); 
    } 
+0

लवली, धन्यवाद। लेकिन व्यक्तिगत रूप से, मैं @ laszlokiss88 उत्तर पसंद करता हूं - यह केवल 2 लाइनें (अनिवार्य रूप से) है और मेरे लिए आसान लगता है। – Bbx

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