ইনভোক কলটিতে নামহীন পদ্ধতি method


131

সিনট্যাক্সটি নিয়ে কিছুটা সমস্যা হচ্ছে যেখানে আমরা একটি নিয়ন্ত্রণের মধ্যে বেনামে একটি প্রতিনিধি কল করতে চাই Iআলভাক করুন।

আমরা বেশ কয়েকটি বিভিন্ন পদ্ধতির চেষ্টা করেছি, সবই লাভ হয়নি।

উদাহরণ স্বরূপ:

myControl.Invoke(delegate() { MyMethod(this, new MyEventArgs(someParameter)); }); 

যেখানে কিছু প্যারামিটার এই পদ্ধতিতে স্থানীয়

উপরেরগুলির ফলে একটি সংকলক ত্রুটি হবে:

বেনাম পদ্ধতিতে 'সিস্টেম.ডেলিগেট' টাইপ করতে পারেন কারণ এটি কোনও প্রতিনিধি প্রকার নয়

উত্তর:


221

কারণ Invoke/ BeginInvokeগ্রহণ করে Delegate(একটি টাইপড প্রতিনিধি না হয়ে), আপনাকে কোন ধরণের প্রতিনিধি তৈরি করতে হবে তা সংকলককে বলতে হবে; MethodInvoker(2.0) বা Action(3.5) সাধারণ পছন্দ (নোট করুন তাদের একই স্বাক্ষর রয়েছে); তাই ভালো:

control.Invoke((MethodInvoker) delegate {this.Text = "Hi";});

যদি আপনাকে প্যারামিটারে পাস করার প্রয়োজন হয়, তবে "ক্যাপচারেড ভেরিয়েবলগুলি" উপায়:

string message = "Hi";
control.Invoke((MethodInvoker) delegate {this.Text = message;});

(সাবধানতা: ক্যাপচার অ্যাসিঙ্ক ব্যবহার করে আপনাকে কিছুটা সতর্ক হওয়া দরকার , তবে সিঙ্কটি ঠিক আছে - যেমন উপরেরটি ঠিক আছে)

আরেকটি বিকল্প হ'ল একটি এক্সটেনশন পদ্ধতি লিখুন:

public static void Invoke(this Control control, Action action)
{
    control.Invoke((Delegate)action);
}

তারপর:

this.Invoke(delegate { this.Text = "hi"; });
// or since we are using C# 3.0
this.Invoke(() => { this.Text = "hi"; });

আপনি অবশ্যই এটি দিয়ে করতে পারেন BeginInvoke:

public static void BeginInvoke(this Control control, Action action)
{
    control.BeginInvoke((Delegate)action);
}

আপনি যদি সি # 3.0 ব্যবহার করতে না পারেন, আপনি সম্ভবত Formবেস-ক্লাসে নিয়মিত উদাহরণ পদ্ধতিতে একই কাজ করতে পারেন ।


এই উত্তরে আমি কীভাবে আপনার প্রথম সমাধানে প্যারামিটারগুলি পাস করতে পারি? আমি এই সমাধানটি বোঝাতে চাইছিলাম: control.Invoke ((মেথডিনভোকার) প্রতিনিধি {this.Text = "হাই";});
uzay95

1
এক্সটেনশনের পদ্ধতিটি এক্সন স্পষ্ট কাস্ট না করে কেন আমন্ত্রণ জানায়?
পি.ব্রায়ান.ম্যাকি

কারণ সংকলক ব্যবহার থেকে এটি অনুমান করতে পারে।
RoboJ1M

1
Form.Load += Loader()Form.Load += new EventHandler(Loader())
পুরানোের

49

আসলে আপনার ডেলিগেট কীওয়ার্ড ব্যবহার করার দরকার নেই। পরামিতি হিসাবে কেবল ল্যাম্বদা পাস করুন:

control.Invoke((MethodInvoker)(() => {this.Text = "Hi"; }));


13

আপনার একটি প্রতিনিধি প্রকার তৈরি করতে হবে। বেনামে পদ্ধতি তৈরির ক্ষেত্রে 'প্রতিনিধি' কীওয়ার্ডটি কিছুটা বিভ্রান্তিকর। আপনি একটি বেনাম প্রতিনিধি তৈরি করছেন না তবে একটি বেনামি পদ্ধতি। আপনার তৈরি পদ্ধতিটি একটি প্রতিনিধি হিসাবে ব্যবহার করা যেতে পারে। এটার মত:

myControl.Invoke(new MethodInvoker(delegate() { (MyMethod(this, new MyEventArgs(someParameter)); }));

8

সম্পূর্ণতার স্বার্থে, এটি কোনও অ্যাকশন পদ্ধতি / বেনামে পদ্ধতির সংমিশ্রণের মাধ্যমেও সম্পন্ন করা যায়:

//Process is a method, invoked as a method group
Dispatcher.Current.BeginInvoke((Action) Process);
//or use an anonymous method
Dispatcher.Current.BeginInvoke((Action)delegate => {
  SomeFunc();
  SomeOtherFunc();
});

Invoke((Action) Process);সেরা উত্তর, আপনাকে ধন্যবাদ!
জিনজিনভ

5

অন্যান্য পরামর্শগুলিতে আমার সমস্যা ছিল কারণ আমি মাঝে মাঝে আমার পদ্ধতিগুলি থেকে মানগুলি ফিরিয়ে দিতে চাই। আপনি যদি রিটার্ন মান সহ মেথডিইনভোকারটি ব্যবহার করার চেষ্টা করেন তবে এটি পছন্দ হবে বলে মনে হয় না। সুতরাং আমি যে সমাধানটি ব্যবহার করি তা এর মতো (এইটিকে আরও সংহত করার উপায় শুনে খুব খুশি হলাম - আমি c #। নেট 2.0 ব্যবহার করছি):

    // Create delegates for the different return types needed.
    private delegate void VoidDelegate();
    private delegate Boolean ReturnBooleanDelegate();
    private delegate Hashtable ReturnHashtableDelegate();

    // Now use the delegates and the delegate() keyword to create 
    // an anonymous method as required

    // Here a case where there's no value returned:
    public void SetTitle(string title)
    {
        myWindow.Invoke(new VoidDelegate(delegate()
        {
            myWindow.Text = title;
        }));
    }

    // Here's an example of a value being returned
    public Hashtable CurrentlyLoadedDocs()
    {
        return (Hashtable)myWindow.Invoke(new ReturnHashtableDelegate(delegate()
        {
            return myWindow.CurrentlyLoadedDocs;
        }));
    }

1

আমি মেথোডিনভোকারের জায়গায় অ্যাকশন ব্যবহার করতে চাই, এটি সংক্ষিপ্ত এবং আরও পরিষ্কার দেখাচ্ছে।

Invoke((Action)(() => {
    DoSomething();
}));

// OR

Invoke((Action)delegate {
    DoSomething();
});

যেমন।

// Thread-safe update on a form control
public void DisplayResult(string text){
    if (txtResult.InvokeRequired){
        txtResult.Invoke((Action)delegate {
            DisplayResult(text);
        });
        return;
    }

    txtResult.Text += text + "\r\n";
}

0

আমি কখনই বুঝতে পারি নি যে এটি সংকলকটির জন্য কেন একটি পার্থক্য তৈরি করে, তবে এটি যথেষ্ট।

public static class ControlExtensions
{
    public static void Invoke(this Control control, Action action)
    {
        control.Invoke(action);
    }
}

বোনাস: হ্যান্ডলিংয়ে কিছু ত্রুটি যুক্ত করুন কারণ সম্ভবত আপনি যদি Control.Invokeকোনও পটভূমি থ্রেড ব্যবহার করে থাকেন তবে আপনি কোনও নিয়ন্ত্রণের পাঠ্য / অগ্রগতি / সক্ষম অবস্থা আপডেট করছেন এবং নিয়ন্ত্রণটি ইতিমধ্যে নিষ্পত্তি হয়েছে কিনা সেদিকে খেয়াল রাখবেন না।

public static class ControlExtensions
{
    public static void Invoke(this Control control, Action action)
    {
        try
        {
            if (!control.IsDisposed) control.Invoke(action);
        }
        catch (ObjectDisposedException) { }
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.