2013-06-21 4 views
8

के लिए डिज़ाइन पैटर्न मेरे पास एक कतार है जो ऑब्जेक्ट को थोड़ी देर लूप में संसाधित करती है। वे अतुल्यकालिक रूप से कहीं न कहीं जोड़ रहे हैं .. इस तरह:गतिशील सी # ऑब्जेक्ट

myqueue.pushback(String value); 

और वे इस तरह कार्रवाई की जाती है:

while(true) 
{ 
    String path = queue.pop(); 
    if(process(path)) 
    { 
     Console.WriteLine("Good!"); 
    } 
    else 
    { 
     queue.pushback(path); 
    } 
} 

अब, बात यह है कि मैं एक टीटीएल की तरह समर्थन करने के लिए इस संशोधित करना चाहते है (रहने का समय) ध्वज, तो फ़ाइल पथ एन बार से अधिक जोड़ा जाएगा।

bool process(String path) फ़ंक्शन हस्ताक्षर को रखते हुए मैं यह कैसे कर सकता हूं? मैं इसे संशोधित नहीं करना चाहता हूं।

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

class JobData 
{ 
    public string path; 
    public short ttl; 

    public static implicit operator String(JobData jobData) {jobData.ttl--; return jobData.path;} 
} 
+1

आपको लगता है कि आपके 'जॉबडाटा' दृष्टिकोण में क्या गलत है? –

+0

अच्छी बात यह है कि मैं प्रक्रिया फ़ंक्शन को संशोधित करना चाहता हूं, मैं सिर्फ 'जॉबडाटा' ऑब्जेक्ट चाहता हूं जो सी # में स्ट्रिंग में एक अंतर्निहित रूपांतरण करने में सक्षम है और गतिशील रूप से कुछ विचारों को स्पष्ट रूप से और स्पष्ट रूप से tll मान – AlexandruC

+0

को कम करता है एक अतिरिक्त अतिरिक्त समाधान जो मैं उल्लेख करूंगा लेकिन समर्थन नहीं करता है, अपने टीटीएल काउंटर के साथ स्ट्रिंग प्रकार में एक एक्सटेंशन विधि जोड़ना है। आदर्श या अनुशंसित नहीं है क्योंकि यह हर जगह स्ट्रिंग करने के लिए एक अर्थहीन विधि जोड़ता है (यहां तक ​​कि एक बहुत ही स्थानीय नामस्थान तक सीमित), लेकिन यह आपकी विशिष्ट समस्या को हल करेगा। –

उत्तर

2

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

http://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words

हमारे प्रयोजनों के लिए, मैं प्रतिशत (%) चरित्र का उपयोग करेंगे। , YAGNI

const int startingTTL = 100; 
const string delimiter = "%"; 

while(true) 
{ 
    String[] path = queue.pop().Split(delimiter.ToCharArray()); 
    int ttl = path.Length > 1?--int.Parse(path[1]):startingTTL; 

    if(process(path[0])) 
    { 
     Console.WriteLine("Good!"); 
    } 
    else if (ttl > 0) 
    { 
     queue.pushback(string.Format("{0}{1}{2}", path[0], delimiter,ttl));    
    } 
    else 
    { 
     Console.WriteLine("TTL expired for path: {0}" path[0]); 
    } 
} 

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

एक और बात। मैं यह इंगित करना चाहता हूं कि यह एक काफी तंग पाश है, जो एक सीपीयू कोर से भागने के लिए प्रवण है। इसके अतिरिक्त, यदि यह .Net कतार प्रकार है और आपका तंग पाश कतार खाली करने के लिए आपके एसिंक्रोनस उत्पादन से आगे आता है, तो आप एक अपवाद फेंक देंगे, जो समय (सत्य) ब्लॉक से बाहर हो जाएगा।आप इस तरह के कोड के साथ दोनों मुद्दों को हल कर सकते हैं: बाधा कि bool process(String path) तो बदल छुआ नहीं किया जा सकता/myqueue में कार्यक्षमता डाल है

while(true) 
{ 

    try 
    { 
     String[] path = queue.pop().Split(delimiter.ToCharArray()); 
     int ttl = path.Length > 1?--int.Parse(path[1]):startingTTL; 

     if(process(path[0])) 
     { 
      Console.WriteLine("Good!"); 
     } 
     else if (ttl > 0) 
     { 
      queue.pushback(string.Format("{0}{1}{2}", path[0], delimiter,ttl));    
     } 
     else 
     { 
      Console.WriteLine("TTL expired for path: {0}" path[0]); 
     } 
    } 
    catch(InvalidOperationException ex) 
    { 
     //Queue.Dequeue throws InvalidOperation if the queue is empty... sleep for a bit before trying again 
     Thread.Sleep(100); 
    } 
} 
1

की तरह आप कर सकते थे सार/"नौकरी प्रबंधक" की कार्यक्षमता को संपुटित कुछ का उपयोग कर। कॉलर से कतार और कार्यान्वयन छुपाएं ताकि आप कॉल करने वाले कॉलर के बिना जो भी चाहें कर सकें। कुछ इस तरह:

public static class JobManager 
{ 
    private static Queue<JobData> _queue; 

    static JobManager() { Task.Factory.StartNew(() => { StartProcessing(); }); } 

    public static void AddJob(string value) 
    { 
     //TODO: validate 

     _queue.Enqueue(new JobData(value)); 
    } 

    private static StartProcessing() 
    { 
     while (true) 
     { 
      if (_queue.Count > 0) 
      { 
       JobData data = _queue.Dequeue(); 
       if (!process(data.Path)) 
       { 
        data.TTL--; 
        if (data.TTL > 0) 
         _queue.Enqueue(data); 
       } 
      } 
      else 
      { 
       Thread.Sleep(1000); 
      } 
     } 
    } 

    private class JobData 
    { 
     public string Path { get; set; } 
     public short TTL { get; set; } 

     public JobData(string value) 
     { 
      this.Path = value; 
      this.TTL = DEFAULT_TTL; 
     } 
    } 

} 

फिर अपने प्रसंस्करण पाश टीटीएल मूल्य संभाल कर सकते हैं।

संपादित करें - एक सरल प्रसंस्करण पाश जोड़ा गया। यह कोड थ्रेड सुरक्षित नहीं है, लेकिन उम्मीद है कि आपको एक विचार देना चाहिए।

+1

मूल प्रश्न कहता है, "मैं यह कैसे कर सकता हूं, बूल प्रक्रिया (स्ट्रिंग पथ) फ़ंक्शन हस्ताक्षर को रखते हुए?"। मुझे यकीन नहीं है कि मैं देखता हूं कि 'कोड (स्ट्रिंग पथ)' आपके कोड के साथ फिट बैठता है ... – Chris

+1

यह अभी भी प्रोसेसिंग लूप –

+1

के भीतर होगा 'थ्रेड स्लीप()' का उपयोग करना एक बुरा विचार है। एक स्थिर 'कन्स्ट्रक्टर' होने से जो कभी वापस नहीं आता है * बेहद बुरा विचार है। – svick

2

हैं। आप void pushback(string path) और string pop() के अपने सार्वजनिक हस्ताक्षर रख सकते हैं, लेकिन आंतरिक रूप से आप अपने टीटीएल को ट्रैक कर सकते हैं। आप स्ट्रिंग पथ को JobData-जैसी कक्षा में लपेट सकते हैं जो आंतरिक कतार में जोड़ा जाता है, या आपके पास पथ द्वारा कुंजीपटल Dictionary हो सकता है। शायद अंतिम pop एड पथ को सहेजने के समान सरल कुछ भी और यदि push उसी पथ है, तो आप यह मान सकते हैं कि यह एक अस्वीकार/असफल आइटम था। इसके अलावा, आपके pop विधि में आप एक ऐसे पथ को भी त्याग सकते हैं जिसे बहुत समय से खारिज कर दिया गया है और आंतरिक रूप से अगले पथ को लाता है ताकि कॉलिंग कोड इस मुद्दे से खुशी से अनजान हो।

+0

पुशिंग कोड की असीमित प्रकृति को देखते हुए, अंतिम पॉप के साथ धक्का मिलान करना बहुत बुरा विचार लगता है। –

+0

हाँ यह सच है। शायद एक रैपिंग डेटा संरचना के साथ चिपकने के लिए सबसे अच्छा है। – tcarvin

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