c# - ControlInvoker बनाम नियंत्रण के लिए कार्रवाई। BginginInvoke




.net delegates (5)

अधिकांश मामलों में यह प्राथमिकता का विषय है, जब तक कि आप DoSomething () विधि का पुन: उपयोग नहीं करना चाहते हैं। इसके अलावा अज्ञात फ़ंक्शन आपके स्कोप्ड वेरिएबल्स को ढेर पर रखेंगे, इससे अधिक महंगा कार्य हो सकता है।

कौन सा सही है और क्यों?

Control.BeginInvoke(new Action(DoSomething), null);

private void DoSomething()
{
    MessageBox.Show("What a great post");
}

या

Control.BeginInvoke((MethodInvoker) delegate { 
    MessageBox.Show("What a great post");
}); 

मुझे लगता है कि मैं वही काम कर रहा हूं, इसलिए MethodInvoker बनाम Action का उपयोग करने का सही समय कब है, या यहां तक ​​कि लैम्ब्डा अभिव्यक्ति लिखना भी सही है?

संपादित करें: मुझे पता है कि लैम्ब्डा बनाम Action लिखने के बीच वास्तव में कोई अंतर नहीं है, लेकिन MethodInvoker एक विशिष्ट उद्देश्य के लिए बनाया जाता है। क्या यह कुछ अलग कर रहा है?


एमएसडीएन प्रति भी:

MethodInvoker एक साधारण प्रतिनिधि प्रदान करता है जिसका प्रयोग शून्य पैरामीटर सूची के साथ एक विधि को आमंत्रित करने के लिए किया जाता है। इस प्रतिनिधि का उपयोग किसी नियंत्रण की आमंत्रण विधि पर कॉल करते समय किया जा सकता है, या जब आपको एक साधारण प्रतिनिधि की आवश्यकता होती है लेकिन आप स्वयं को परिभाषित नहीं करना चाहते हैं।

दूसरी तरफ एक एक्शन में 4 पैरामीटर लग सकते हैं।

लेकिन मुझे नहीं लगता कि MethodInvoker और Action के बीच कोई अंतर है क्योंकि वे दोनों एक ऐसे प्रतिनिधि को आसानी से समाहित करते हैं जो एक पारेमटर नहीं लेता है और शून्य देता है

यदि आप उनकी परिभाषाओं को देखते हैं तो आप इसे आसानी से देखेंगे।

public delegate void MethodInvoker();
public delegate void Action();

बीटीडब्ल्यू आप अपनी दूसरी लाइन भी लिख सकते हैं।

Control.BeginInvoke(new MethodInvoker(DoSomething), null);

दोनों समान रूप से सही हैं, लेकिन Control.Invoke लिए प्रलेखन बताता है कि:

प्रतिनिधि EventHandler का एक उदाहरण हो सकता है, जिस स्थिति में प्रेषक पैरामीटर में यह नियंत्रण होगा, और ईवेंट पैरामीटर में EventArgs.Empty होगा। प्रतिनिधि भी MethodInvoker, या किसी अन्य प्रतिनिधि का उदाहरण हो सकता है जो शून्य पैरामीटर सूची लेता है। इवेंट हैंडलर या मेथडइवॉकर प्रतिनिधि को कॉल किसी अन्य प्रकार के प्रतिनिधि को कॉल से तेज़ होगा।

तो MethodInvoker एक और अधिक कुशल विकल्प होगा।


प्रत्येक समाधान के लिए मैं 131072 (128 * 1024) पुनरावृत्तियों (एक अलग धागे में) चलाता हूं। वीएस -2010 प्रदर्शन सहायक इस परिणाम देते हैं:

  • केवल-पढ़ने के लिए MethodInvoker: 5664.53 (+ 0%)
  • नया विधि इनवॉकर: 5828.31 (+ 2.89%)
  • MethodInvoker में फ़ंक्शन कास्ट: 5857.07 (+ 3.40%)
  • केवल पढ़ने के लिए कार्य: 6467.33 (+ 14.17%)
  • नई कार्यवाही: 6829.07 (+ 20.56%)

प्रत्येक पुनरावृत्ति पर एक नई कार्रवाई के लिए बुलाओ

    private void SetVisibleByNewAction()
    {
        if (InvokeRequired)
        {
            Invoke(new Action(SetVisibleByNewAction));
        }
        else
        {
            Visible = true;
        }
    }

केवल पढ़ने के लिए कॉल करें, कन्स्ट्रक्टर में निर्माण करें, प्रत्येक पुनरावृत्ति पर कार्रवाई करें

    // private readonly Action _actionSetVisibleByAction
    // _actionSetVisibleByAction= SetVisibleByAction;
    private void SetVisibleByAction()
    {
        if (InvokeRequired)
        {
            Invoke(_actionSetVisibleByAction);
        }
        else
        {
            Visible = true;
        }
    }

प्रत्येक पुनरावृत्ति पर एक नया MethodInvoker पर कॉल करें।

    private void SetVisibleByNewMethodInvoker()
    {
        if (InvokeRequired)
        {
            Invoke(new MethodInvoker(SetVisibleByNewMethodInvoker));
        }
        else
        {
            Visible = true;
        }
    }

केवल पढ़ने के लिए कॉल करें, कन्स्ट्रक्टर में बिल्ड करें, प्रत्येक पुनरावृत्ति पर MethodInvoker

    // private readonly MethodInvoker _methodInvokerSetVisibleByMethodInvoker 
    // _methodInvokerSetVisibleByMethodInvoker = SetVisibleByMethodInvoker;
    private void SetVisibleByMethodInvoker()
    {
        if (InvokeRequired)
        {
            Invoke(_methodInvokerSetVisibleByMethodInvoker);
        }
        else
        {
            Visible = true;
        }
    }

प्रत्येक पुनरावृत्ति पर MethodInvoker में फ़ंक्शन कास्ट पर कॉल करें

    private void SetVisibleByDelegate()
    {
        if (InvokeRequired)
        {
            Invoke((MethodInvoker) SetVisibleByDelegate);
        }
        else
        {
            Visible = true;
        }
    }

"नई क्रिया" समाधान के लिए कॉल का उदाहरण:

    private void ButtonNewActionOnClick(object sender, EventArgs e)
    {
        new Thread(TestNewAction).Start();
    }

    private void TestNewAction()
    {
        var watch = Stopwatch.StartNew();
        for (var i = 0; i < COUNT; i++)
        {
            SetVisibleByNewAction();
        }
        watch.Stop();
        Append("New Action: " + watch.ElapsedMilliseconds + "ms");
    }

सिस्टम में क्रिया परिभाषित की गई है, जबकि MethodInvoker को System.Windows.Forms में परिभाषित किया गया है - आप कार्रवाई का उपयोग बंद कर सकते हैं, क्योंकि यह अन्य स्थानों पर पोर्टेबल है। आपको MethodInvoker की तुलना में पैरामीटर के रूप में कार्य स्वीकार करने वाले और स्थान भी मिलेंगे।

हालांकि, प्रलेखन इंगित करता है कि Control.Invoke () में EventHandler या MethodInvoker के प्रकार के प्रतिनिधियों को कॉल किसी अन्य प्रकार की तुलना में तेज़ होगा।

वे किस नामस्थान में हैं, मुझे विश्वास नहीं है कि एक्शन और मेथडइवॉकर के बीच एक सार्थक कार्यात्मक अंतर है - वे अनिवार्य रूप से दोनों परिभाषित हैं:

public delegate void NoParamMethod();

एक तरफ के रूप में, एक्शन में कई अधिभार होते हैं जो पैरामीटर को पारित करने की अनुमति देते हैं - और यह सामान्य है ताकि वे टाइपएफ़ हो सकें।





invoke