2011-05-03 93 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