2011-01-02 16 views
13

Mam aplikację wygrywającą formularze z listboksami wyświetlającymi metody (według atrybutów). Próbuję dynamicznie wywoływać metody w wątku, używając odbicia, aby uzyskać informacje o metodzie z wybranej wartości pola listy. Jednak wywołując Methodinfo.Invoke otrzymuję ten wewnętrzny wyjątek "Metoda niestatyczna wymaga docelowego C#".Metoda niestatyczna wymaga celu C#

Oto mój kod (należy pamiętać, że jestem wciąż nowe do C# i programowania w ogóle.)

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"); 
    } 
} 

Odpowiedz

19

Próbujesz wywołać metodę non-statycznego bez podania odniesienia instancji obiektu, dla którego ta metoda należy się powołać. Ponieważ pracujemy z metod MainForm klasy, należy podać przedmiot MainForm typu w pierwszym parametrze MethodInfo.Invoke(Object, Object[]), w przypadku:

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

Przykład wykonywania metody w oddzielnym wątku:

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); 
} 
+0

Dzięki dla szybkiej odpowiedzi. Po wypróbowaniu tego kodu wywołuje on wybraną metodę na wątku głównym, a nie na UIthread. (Te nazwy wątków są niejednoznaczne, przepraszam za to). –

+0

Wywołujesz jawnie tę metodę w głównym wątku, używając 'testListBox.BeginInvoke()'. 'MethodInfo.Invoke()' wykonuje w wątku, z którego został wywołany. – max

+0

Ah widzę. Wygląda na to, że będę musiał ponownie przemyśleć mój kod. Czy masz jakieś pomysły, w jaki sposób mogę uzyskać wybraną metodę do wywołania w wątku innym niż główny formularz? –

Powiązane problemy