2012-11-06 38 views
18

मैं उपयोगकर्ता को प्रगति पट्टी प्रदर्शित करते समय कार्यकर्ता थ्रेड पर कुछ संचालन निष्पादित करना चाहता हूं। मैं एक वर्गअज्ञात संख्या के पैरामीटर के साथ एक विधि निष्पादित करने के लिए .NET कार्रवाई का उपयोग कैसे करें?

public class ProgressBar 
{ 
    public void StartAsyncTask(Action action) 
    { 
     Task t = new Task(action); 
     t.start(); 
    } 
} 

मुझे पता चला कि मैं निम्नलिखित तरीके से StartAsyncTask के लिए किसी भी विधि को भेज सकते हैं बना लिया है:

ProgressBar pb = new ProgressBar(); 
    pb.StartAsyncTask(() => DoSomething(15, "something")); 

    public void DoSomething(int i, string s) 
    { 
     //do something 
    } 

सबसे पहले, मैं समझने के लिए क्या है नहीं कर पा रहे और लैम्ब्डा अभिव्यक्ति कैसा है - () => - अनुवादित और Action ऑब्जेक्ट एक अज्ञात संख्या के पैरामीटर के साथ एक प्रतिनिधि को पास करता है।

मैं अपने प्रोग्रेसबार के साथ BackgroundWorker का उपयोग करना चाहता हूं लेकिन इस मामले में मुझे कार्रवाई का आह्वान करना होगा। तो कुछ इस तरह:

void m_backgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    Action action = e.Argument as Action; //same action here passed through EventArgs 
    //but already in a worker thread so no need for the Task object 

    //and now i need to somehow invoke the action object but i don't know what the parameters are. 

    action.Invoke(?); 
} 

कैसे यह संभव पहले उदाहरण में StartAsyncTask(Action action) विधि में पैरामीटर जानने के बिना कार्रवाई अमल करने के लिए है?

इस मामले में कार्रवाई का आह्वान करते समय मुझे पैरामीटर जानने की आवश्यकता क्यों है?

"Action" का उपयोग करने के लिए कैसे/क्यों/कब उपयोग करें, यहां तक ​​कि अगर मैं एमएसडीएन दस्तावेज और कुछ अन्य धागे पढ़ता हूं तो भी मुझे अस्पष्ट नहीं है। इस पर कोई भी जानकारी मेरी मदद करेगी।

+0

आप जब यह बुला मापदंडों पता करने की जरूरत है (यह तर्क के रूप में params object[] args लेता है) .. अन्यथा (अगर यह संभव हो गया था पैरामीटर पास नहीं) फ़ंक्शन में कोई पैरामीटर नहीं होगा .. इसलिए अपना पहला 'पैरामीटर बनाना। कुछ' कॉल 'NullReferenceException' फेंक दें। –

उत्तर

47

मुझे लगता है कि आप चीजों को थोड़ा अधिक समझ रहे हैं। तो चलिए शीर्ष से शुरू करते हैं:

  1. एक लैम्ब्डा अभिव्यक्ति एक विधि निष्पादन का संदर्भ देने के लिए एक संकेत है। उदाहरण:

    x => x + 3 
    

    सबसे बुनियादी स्तर पर, यह एक समारोह है कि 1 इनपुट, x लेता है, और फिर x + 3 के बराबर एक मान देता है का प्रतिनिधित्व कर रहा है। अपनी स्थिति में तो, आपकी अभिव्यक्ति:

    () => DoSomething(15, "Something") 
    

    एक विधि 0 मापदंडों लेने, और फिर विधि DoSomething(15, "Something") लागू प्रतिनिधित्व करता है। संकलक दृश्यों के पीछे है जो कि Func या Action आपके लिए प्रतिनिधि है। तो यह प्रभाव में है:

    new Action(delegate() 
    { 
        DoSomething(15, "Something") 
    }); 
    

    मेरी सरल अभिव्यक्ति का संकलक पुनर्लेखन ऊपर होगा:

    new Func<int, int>(delegate(int x) 
    { 
        return x + 3; 
    }); 
    
  2. आगे, यदि आप बाद में एक कार्रवाई आह्वान करने के लिए चाहते हैं, करने के लिए वाक्य रचना तो है काफी सरल:

    Action someMethod = new Action(() => { Console.WriteLine("hello world"); })); 
    someMethod(); // Invokes the delegate 
    

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

    एक जैसे काम करते आसान है:

    Func<int, int> previousGuy = x => x + 3; 
    var result = previousGuy(3); // result is 6 
    
  3. अंत में, यदि आप को लागू करने की एक विधि के साथ पास करना चाहते हैं, और आप उस बिंदु पर मापदंडों के लिए संदर्भ की जरूरत नहीं है, तो आप बस लपेट कर सकते हैं अपने एक कार्रवाई में कॉल करें और बाद में इसका आह्वान करें। उदाहरण के लिए:

    var myAction = new Action(() => 
        { 
          // Some Complex Logic 
          DoSomething(15, "Something"); 
          // More Complex Logic, etc 
        }); 
    
    InvokeLater(myAction); 
    
    public void InvokeLater(Action action) 
    { 
         action(); 
    } 
    

    डेटा के सभी अपने विधि का एक बंद में कब्जा, और इस तरह से सहेजा जाता है है। तो यदि आप e.Argument संपत्ति के साथ अपने ईवेंट में Action के साथ पास करने का प्रबंधन कर सकते हैं, तो आपको (e.Argument as Action)() पर कॉल करना होगा।

2

आपको लगता है कि प्रतिनिधि पर DynamicInvoke() उपयोग नहीं कर सकते

action.DynamicInvoke(arg1, arg2, arg3);