2011-11-23 15 views
7

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

public void SendEmailsRepeatedly(IEnumerable<SimpleEmail> emails, int sendRepeatedlyDelayMS) 
{ 
    Tokenizer tokenizer = new StandardTokenizer(); 

    sendRepeatedlyTimer = new Timer(
     SendRepeatedlyCallback, 
     (Action)delegate() 
     { 
      TokenizeAndSendEmails(emails, tokenizer); 
     }, 
     0, 
     sendRepeatedlyDelayMS); 
} 

private void SendRepeatedlyCallback(object state) 
{ 
    if (!abort) 
    { 
     Action sendEmails = (Action)state; 
     sendEmails(); 
    } 
} 

तो मेरा सवाल है, क्या यह एक प्रमुख हैक है? क्या ऐसा करने के लिए कोई बेहतर या अनुशंसित तरीका है?

उत्तर

7

एक मामले के रूप में आप एक वर्ग द्वारा सभी मापदंडों को संपुटित कर सकते हैं :

public sealed class SendEmailParameters 
{ 
    public int RepeatCount { get; private set; } 
    ... 
} 

private void SendRepeatedlyCallback(object state) 
{ 
    var parameters = (SendEmailParameters)state; 

    // ... 
} 
+2

मैं इसे आपको देने जा रहा हूं क्योंकि यह शायद सबसे अधिक "पठनीय" दृष्टिकोण है, और मुझे यकीन है कि मेरे सहकर्मी पहले से ही मेरे अधिकांश कोड के साथ काफी उलझन में हैं। –

+1

मुझे इसमें कोई लाभ नहीं दिख रहा है। जब संकलक आपके लिए यह बॉयलरप्लेट काम कर सकता है तो खुद को कक्षा क्यों बनाएं? –

+3

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

6

यह बिल्कुल ठीक है। सी # 3 के रूप में मैं व्यक्तिगत रूप से बजाय एक लैम्ब्डा अभिव्यक्ति का उपयोग करना चाहते हैं, - और एक अलग स्थानीय चर का उपयोग एक विधि के बीच में कलाकारों से बचने के लिए:

public void SendEmailsRepeatedly(IEnumerable<SimpleEmail> emails, 
           int sendRepeatedlyDelayMS) 
{ 
    Tokenizer tokenizer = new StandardTokenizer(); 
    Action action =() => TokenizeAndSendEmails(emails, tokenizer);  
    sendRepeatedlyTimer = new Timer(SendRepeatedlyCallback, action, 0, 
            sendRepeatedlyDelayMS); 
} 
+0

बहुत प्रभावशाली। मैं थोड़ी उलझन में हूं कि विधि के बीच में क्यों डालना बुरा है? क्या यह सिर्फ पठनीयता के लिए है या क्या इससे वास्तविक समस्याएं पैदा होंगी? –

+3

@RepoMan: यह पठनीयता के लिए "बस" है - लेकिन यह मेरे दृष्टिकोण से एक बड़ा "बस" है :) –

1

क्या वे पैरामीटर ज्ञात हैं? फिर आपको आवश्यक सभी संपत्तियों के साथ एक उद्देश्य निर्मित वस्तु भेजें।

1

यह ठीक है। आप अपना खुद का प्रकार भी बना सकते हैं और उस कॉलम को शामिल करने के लिए उपयोग कर सकते हैं जिसे आप अपने कॉलबैक में पास करना चाहते हैं। बस 'ऑब्जेक्ट स्टेटस' पैरामीटर को उस प्रकार के प्रकार पर डालें जिसे आपने बनाया है और अपने प्रकार के गुणों को पढ़ा है।

0

आप एक ऐसा वर्ग बना सकते हैं जो आपको पारित करने वाले सभी तर्कों को समाहित करता है, या आप लैम्ब्डा अभिव्यक्ति का उपयोग कर सकते हैं। ऐसा कुछ बहुत करीब होना चाहिए:

public void SendEmailsRepeatedly(IEnumerable<string> emails, int sendRepeatedlyDelayMS) 
{ 
    AutoResetEvent resetEvent = new AutoResetEvent(false);  
    Tokenizer tokenizer = new StandardTokenizer();   

    var timer = new Timer(x => SendRepeatedlyCallback(x, emails, tokenizer), resetEvent, 0, sendRepeatedlyDelayMS); 
} 

static void SendRepeatedlyCallback(object state, IEnumerable<string> emails, StandardTokenizer tokenizer) 
{ 
    ... 
} 
संबंधित मुद्दे

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