Non-static method requires a target C#
Asked Answered
P

1

14

I have a win form app with a listbox displaying methods (by attribute). I am attempting to dynamically invoke methods in a thread, using reflection to get method info from the selected value of the the list box. However, when calling Methodinfo.Invoke I am getting this inner exception "Non-static method requires a target C#".

Here's my code (keep in mind I'm still new to c# and programming in general.)

private void PopulateComboBox()
{//Populates list box by getting methods with declared attributes
    MethodInfo[] methods = typeof(MainForm).GetMethods();

    MyToken token = null;
    List<KeyValuePair<String, MethodInfo>> items =
        new List<KeyValuePair<string, MethodInfo>>();

    foreach (MethodInfo method in methods)
    {
        token = Attribute.GetCustomAttribute(method,
            typeof(MyToken), false) as MyToken;
        if (token == null)
            continue;

        items.Add(new KeyValuePair<String, MethodInfo>(
            token.DisplayName, method));

    }

    testListBox.DataSource = items;
    testListBox.DisplayMember = "Key";
    testListBox.ValueMember = "Value";
}

public void GetTest()
{//The next two methods handle selected value of the listbox and invoke the method.

    if (testListBox.InvokeRequired)
        testListBox.BeginInvoke(new DelegateForTest(functionForTestListBox));
    else
        functionForTestListBox();

}

public void functionForTestListBox()
{
    _t = testListBox.SelectedIndex;

    if (_t < 0)
        return;

    _v = testListBox.SelectedValue;

    method = _v as MethodInfo;


    if (method == null)
        return;

    _selectedMethod = method.Name;

    MessageBox.Show(_selectedMethod.ToString());

    method.Invoke(null, null);//<----Not sure about this. it runs fine when I dont invoke in a thread.

    counter++;

}
private void runTestButton_Click(object sender, EventArgs e)
{// Click event that calls the selected method in the thread
    if (_serverStatus == "Running")
    {

        if (_testStatus == "Not Running")
        {

            // create Instance new Thread and add function
            // which will do some work
            try
            {
                SetupTestEnv();
                //functionForOutputTextBox();
                Thread UIthread = new Thread(new ThreadStart(GetTest));
                UIthread.Name = "UIThread";
                UIthread.Start();
                // Update test status
                _testStatus = "Running";
                //Make thread global
                _UIthread = UIthread;
            }
            catch
            {
                    MessageBox.Show("There was an error at during the test setup(Note: You must install each web browser on your local machine before attempting to test on them).");
            }

        }
        else
        {
            MessageBox.Show("Please stop the current test before attempt to start a new one");
        }
    }
    else
    {
        MessageBox.Show("Please make sure the server is running");
    }
}
Protuberancy answered 2/1, 2011 at 4:53 Comment(0)
R
22

You are trying to invoke non-static method without providing object instance reference, for which this method should be invoked. Since you are working with methods of MainForm class, you should provide object of MainForm type in the first parameter of MethodInfo.Invoke(Object, Object[]), in your case:

if(method.IsStatic)
    method.Invoke(null, null);
else
    method.Invoke(this, null);

Example of executing method on separate thread:

public MethodInfo GetSelectedMethod()
{
    var index = testListBox.SelectedIndex;
    if (index < 0) return;
    var value = testListBox.SelectedValue;
    return value as MethodInfo;
}

private void ThreadProc(object arg)
{
    var method = (MethodInfo)arg;
    if(method.IsStatic)
        method.Invoke(null, null)
    else
        method.Invoke(this, null);
}

private void RunThread()
{
    var method = GetSelectedMethod();
    if(method == null) return;
    var thread = new Thread(ThreadProc)
    {
        Name = "UIThread",
    };
    thread.Start(method);
}
Rm answered 2/1, 2011 at 5:3 Comment(4)
Thanks for the quick response. After trying this code though, it invokes the selected method on the mainform thread not the UIthread. (Those thread names are ambiguous, sorry about that).Protuberancy
You are explicitly calling this method on mainform thread by using testListBox.BeginInvoke(). MethodInfo.Invoke() performs on the thread from which it was called.Rm
Ah i see. Well it looks like a I will have to rethink my code. Do you have any ideas on how I could go about getting the selected method to invoke in a thread different than the main form?Protuberancy
You just need to pass selected method to your "UIThread" (look at Thread(ParameterizedThreadStart) constructor for example, which allows passing a parameter). Then call MethodInfo.Invoke(this, null) without Control.BeginInvoke in your thread function.Rm

© 2022 - 2024 — McMap. All rights reserved.