【问题标题】:Execute a method/set property in a specific thread在特定线程中执行方法/设置属性
【发布时间】:2011-05-03 16:04:54
【问题描述】:

大家好 我对所有这些多线程的东西有点陌生,所以如果我解释得不好,请原谅:)

假设我有两个类:

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,需要在主应用程序线程中执行的代码也不会在主应用程序线程中执行(我不这么认为) 我试过在代码中输出当前线程名,并没有输出主应用线程名。

有没有办法可以做到这一点? 如果我解释得很糟糕,请告诉我:) 谢谢!

【问题讨论】:

  • 请解释为什么您需要在主(或其他)线程上执行该代码。您使用InvokeMember 的方法是完全错误的,如果不澄清您的意图,您就不能指望一个与您的实际情况相匹配的真正有用的答案。
  • 请指定 WinForms 或 WPF
  • 抱歉信息不足。这不是 WinForms 或 WPF,它是一个控制台应用程序。它需要在主线程上执行的原因有很多,其中一个是因为我正在构建一个使用 Lidgren 网络库的应用程序,并且我只能在库正在侦听的线程上发送网络消息。

标签: c# .net multithreading invoke


【解决方案1】:

有多种方法可以做到这一点,但我的首选方法如下:

   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

【讨论】:

    【解决方案2】:

    InvokeMember 只是使用反射执行成员的一种方式。它与线程无关。

    我怀疑您真的在寻找 Control.InvokeDispatcher.Invoke(或非阻塞 BeginInvoke 等效项)。

    当然,您需要引用适当的控件或调度程序,然后创建适当的委托以在另一个线程上执行。如果您寻找有关 Windows 窗体多线程(或 WPF)的教程,您应该会找到很多示例。 (我的网络连接现在很垃圾,否则我会为你找到一个像样的。)

    编辑:既然您已经明确它是一个控制台应用程序,那么您将不得不制定某种形式的消息泵。除非线程以某种方式侦听消息,否则无法强制它执行另一段代码。我没有使用过你所说的库——但如果它迫使你在特定线程上执行代码,那么它应该提供一些等价的 Control.Invoke 等。

    【讨论】:

    • 这里有点困惑。我认为我不能使用 Control.Invoke,因为这与 System.Windows.Forms 对象无关。我可以使用 BeginInvoke,它会在我想要的线程中执行吗?还是我应该调查这个 Dispatcher.Invoke 的事情?
    • @Jamie:您没有向我们提供有关上下文的足够信息。你在写什么样的应用程序?您谈论的是“主应用程序线程” - 但如果您要能够要求它运行任意代码,该线程必须运行消息泵或类似的东西。
    • 我正在研究 BeginInvoke,我认为这正是我所需要的。是否可以从 MethodInfo 中获取一个委托,我可以调用 BeginInvoke ?我有很多方法,我真的不想逐个检查并为它们指定一个代表。谢谢
    • @Jamie:不,您不想调用 BeginInvoke on 代表。您想将委托传递给 BeginInvoke。你应该看看 Delegate.CreateDelegate 从 MethodInfo 创建一个委托。
    • 哦,我刚在MSDN上找到一篇文章。 Dispatcher.BeginInvoke(delegateobj, etc) 会起作用吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-02
    • 1970-01-01
    • 1970-01-01
    • 2012-11-28
    相关资源
    最近更新 更多