2011-05-03 85 views
0

大家好 我是一種新的這一切多線程的東西,所以請原諒我,如果我來解釋一下這個厲害:)執行的方法/設置屬性

比方說,我有兩個類:

class abc { 
    public string SomeProperty { 
     get { return something; } 
     set { /* This code has to execute in the main application thread */ } 
    } 

    public void SomeMethod() { 
     /* This code also has to execute in the main application thread */ 
    } 
} 

class def { 
    abc obj; 

    public def() { 
     abc = new obj(); 
    } 

    public void SomeMethod() { 
     abc.SomeProperty = "SomeValue"; 
     abc.SomeMethod(); 
    } 
} 

我遇到的問題是獲取SomeProperty和SomeMethod在主應用程序線程上執行。我曾嘗試:

abc.GetType().InvokeMember("SomeProperty", System.Reflection.BindingFlags.SetProperty, null, abc, new object[] { "SomeValue" }); 
abc.GetType().InvokeMember("SomeMethod", System.Reflection.BindingFlags.InvokeMethod, null, abc, null); 

但是,沒有被主應用程序線程中執行它需要在主應用程序線程來執行代碼,即使使用InvokeMember(我不這麼認爲反正) 我有嘗試在代碼中輸出當前線程名稱,並且不輸出主應用程序線程名稱。

有沒有辦法可以做到這一點? 如果我已經解釋不好,只是讓我知道:) 謝謝!

+2

請解釋爲什麼** **你需要執行在主要(或其他)線程上的代碼。你使用'InvokeMember'的方法顯然是錯誤的,沒有明確你的意圖,你不能指望一個真正有用的答案,將符合你的實際案例。 – 2011-05-03 16:08:47

+0

並請指定WinForms或WPF – 2011-05-03 16:11:08

+0

抱歉缺少信息。這不是WinForms或WPF,它是一個控制檯應用程序。有很多原因需要在主線程上執行,其中之一是因爲我正在構建一個使用Lidgren網絡庫的應用程序,並且我只能在該庫正在監聽的線程上發送網絡消息。 – Jamie 2011-05-03 17:17:59

回答

1

InvokeMember只是一種使用反射來執行成員的方法。它與線程無關。

我懷疑你真的在尋找Control.InvokeDispatcher.Invoke(或非阻塞的BeginInvoke等價物)。

當然,您需要對適當的控件或調度程序的引用,然後創建一個適當的委託在另一個線程上執行。如果你在Windows Forms多線程(或WPF)上尋找教程,你應該找到很多例子。 (我的網絡連接目前是垃圾,否則我會找到一個適合你的。)

編輯:現在,你已經明確說它是一個控制檯應用程序,你將不得不制定一些形式的消息泵。除非線程以某種方式偵聽消息,否則無法強制它執行另一個代碼。我沒有使用過你提到過的庫 - 但是如果它迫使你在特定的線程上執行代碼,那麼它應該提供一些等效的Control.Invoke等。

+0

這裏有點困惑。我不認爲我可以使用Control.Invoke,因爲這與System.Windows.Forms對象無關。我可以使用BeginInvoke,它會在我想要的線程中執行嗎?或者我應該調查這個Dispatcher.Invoke的事情? – Jamie 2011-05-03 16:12:47

+1

@Jamie:你沒有給我們足夠的上下文信息。你在寫什麼樣的應用程序?你談論的是一個「主應用程序線程」 - 但是如果你能夠讓它運行任意代碼,那麼這個線程必須運行一個消息泵或類似的東西。 – 2011-05-03 16:15:02

+0

我正在調查BeginInvoke,我認爲這正是我需要的。是否有可能從MethodInfo中獲得一個委託,我可以調用BeginInvoke?我有非常多的方法,我並不是真的想要通過每一個方法來爲他們做一個代表。謝謝 – Jamie 2011-05-03 17:09:12

2

有很多方法可以做到這一點,但我的首選的方法如下:

protected void setTransactionButton(Boolean enabled) 
    { 
     (new Task(() => 
     { 
      transcriptQuitButton.Enabled = enabled; 
     })).Start(uiScheduler); 
    } 

在我的初始化代碼我呼籲這一點:

uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 

這樣做是什麼讓事件採取的UI線程地方和擺脫的需要BeginInvoke

有各種不同的地方,你可以找到BeginInvoke,但如果你可以使用匿名函數,並在一個文章是在這裏:

http://visualstudiomagazine.com/articles/2009/02/01/use-lambda-expressions-for-abstract-delegates.aspx