2010-06-15 51 views
0
MethodInfo mi = typeof(NotifyIcon).GetMethod("ShowContextMenu", BindingFlags.Instance | BindingFlags.NonPublic); 
mi.Invoke(notify, null); 

這引發以下異常:
{"Exception has been thrown by the target of an invocation."}調用目標投擲無效跨線程操作異常

用下面的內部異常:
"Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on."

如果我註釋掉的代碼行設置上下文菜單項的圖像,然後停止拋出異常。

任何想法?

回答

0

您正在更新創建它們的線程以外的線程上的UI控件。這是不允許的。

在常規代碼中,您可以使用Control.InvokeRequired屬性。

假設你有兩個按鈕的形式,這裏兩個標籤是如何從另一個線程做更新:

private void button1_Click(object sender, EventArgs e) 
{ 
    //force execution on another thread 
    new Thread(updateLabelThreaded).Start(); 
} 

private void button2_Click(object sender, EventArgs e) 
{ 
    //force execution on another thread 
    new Thread(updateLabelReflect).Start(); 
} 

private void updateLabelThreaded() 
{ 
    if (!label1.InvokeRequired) 
    { 
     //if we are on the correct thread, do a trivial update 
     label1.Text = "something"; 
    } 
    else 
    { 
     //else invoke the same method, on the UI thread 
     Invoke(new Action(updateLabelThreaded), null); 
    } 
} 

private void updateLabelReflect() 
{ 
    Control ctrl = label2; 

    PropertyInfo pi = typeof (Label).GetProperty("InvokeRequired"); 
    bool shouldInvoke = (bool) pi.GetValue(ctrl, null); 
    if (!shouldInvoke) 
    { 
     //if we are on the correct thread, reflect whatever is neccesary - business as usual 
     PropertyInfo txtProp = typeof (Label).GetProperty("Text"); 
     txtProp.SetValue(ctrl, "Something 2", null); 
    } 
    else 
    { 
     //else invoke the same method, on the UI thread 
     Invoke(new Action(updateLabelReflect), null); 
    } 
    } 
0

您可能會產生混淆的MethodInfoInvoke方法,它只是調用了委託當前線程,Control.Invoke在UI線程上調用委託。

如果您嘗試從正確的UI線程以外的線程訪問UI元素,則會得到此異常。

基本上你需要在UI線程上執行這段代碼。

是否有任何理由試圖通過反射而不是直接調用ShowContextMenu?您可能只需要類似(假設C#3):

MethodInvoker action =() => notify.ShowContextMenu(); 
someControl.Invoke(action); 
+0

ShowContextMenu是非公開的,所以它必須通過反射? 它工作正常,如果我沒有設置ToolStripItem圖像。 另外,如果它是在ToolStripItem圖像被設置之前執行的,那麼即使在設置圖像之後,它也會在程序持續時間內正確顯示上下文菜單,而不會引發異常。 – sqwerty 2010-06-15 14:19:09

+1

@sqwerty:如果'ShowContextMenu'是非公開的,你根本不應該調用它。通過反思調用非公衆成員只是要求麻煩 - 他們可以在不同版本之間進行更改。如果你真的想要這樣做,那麼只需使用'Control.Invoke'在正確的線程上完成它。它發生失敗的確切情況無關緊要:您正在從非UI線程中觸摸UI。不要這樣做。 – 2010-06-15 15:33:01