哪个C#程序集包含Invoke方法?

5

备选问题:为什么VS10如此热衷于抱怨Invoke?

在我不断努力成为世界上最好的C#程序员的过程中,我已经决定线程是一个好东西™。

MSDN有一篇有关制作控件线程安全调用的有用文章,但它(以及似乎每一篇有关该主题的文章)间接地提到了一个名为Invoke的方法。有时甚至是BeginInvoke,这据我所知是更受欢迎的

所有这些都很好,如果我能让Visual Studio识别Invoke。MSDN说它包含在System.Windows.Forms程序集中,但我已经使用了它。为了确保,我也尝试了使用System.Threading,但没有成功。

我需要跳过哪些障碍才能使Invoke正常工作?


“Visual Studio recognize Invoke” 是什么意思?是指智能感知吗? - Stefan Steinegger
你是在谈论在当前执行线程不同的线程上创建的控件上调用方法吗? - Ryan Conrad
6
当你成为世界上最优秀的C#程序员时,你可能会意识到线程是非常糟糕的事情,或者说,显式地管理线程是一件糟糕的事情。 - Eric Lippert
@Eric 你引发了另一个问题:https://dev59.com/-nA75IYBdhLWcg3wxsJn - Tom Wright
6个回答

4

Invoke 在控件内部,即:Control.Invoke();

直接调用 Invoke 是不可能的,因为在 System.Windows.Forms 中没有这样的方法。Invoke 方法是控件成员。

下面是我之前制作的一个示例

public delegate void AddListViewItemCallBack(ListView control, ListViewItem item);
public static void AddListViewItem(ListView control, ListViewItem item)
{
    if (control.InvokeRequired)
    {
        AddListViewItemCallBack d = new AddListViewItemCallBack(AddListViewItem);
        control.Invoke(d, new object[] { control, item });
    }
    else
    {
        control.Items.Add(item);
    }
}

3
您需要在包含Invoke的东西的实例上调用它 - 如果您正在使用Windows Forms,则应该是一个控件:
control.Invoke(someDelegate);

或者对于表单内的代码,您可以使用隐式的this引用:

Invoke(someDelegate);

您不需要经过任何特殊的步骤。如果 Visual Studio 报错,请指定编译器错误和引起报错的代码。这里的 Invoke 没有什么特别之处。


2

Winform中的InvokeControl类的一个实例方法 - 你只需要一个控件的实例(在很多情况下可以是this)。例如:

txtBox.Invoke(...);

如果你想要抽象化,也可以通过接口或同步上下文访问它,但最简单的方法是通过事件在UI中处理它,这样控件就会方便地可用。


1
如果你真的想成为世界上最好的C#程序员,你必须学会线程不是一个好东西,除非正确使用。
跨线程更新UI通常意味着你正在滥用线程。
无论如何,仅仅使用 using System.Windows.Forms 是不够的,你还需要将其添加到引用中。在项目资源管理器中右键单击 References,然后选择 Add References 并选择 System.Windows.Forms

哎呀,谢谢!你把我搞糊涂了。 (这里有另一个你可能想回答的问题:https://dev59.com/-nA75IYBdhLWcg3wxsJn) - Tom Wright
“在不同线程中更新用户界面通常意味着您滥用了线程。”哇,这对我来说是新的。所以,如果我将长时间的分析操作放在后台线程中以保持UI的响应性,但用户希望快速看到增量结果,因此我的后台线程定期将结果发布回UI线程,这就是滥用吗?那么现在你会揭示更好的解决方案吗? - Conrad Albrecht
2
是的,这很简单:使用事件。后台线程提供了一个事件,UI可以订阅它,例如“文件已复制”,“数字已计算”等。UI可以订阅它,如果您将代码从WinForms切换到WPF,实现多语言UI,将无需修改后台工作程序,更改无聊的对话框为花哨的对话框等。 - user253984
2
@Conrad:dbemerlin 提出了一个很好的观点。另一种思考方式是,分析操作的业务是分析,而不是 UI。在分析函数中,不应该有任何直接更新 UI 的逻辑;这不是它所关心的。如果分析函数作为服务提供回调来描述其当前状态,那就很好,这是它的职责。该回调对 UI 的影响可以由 UI 代码处理。 - Eric Lippert
1
好的,这只是对意义的误解。实际上我的BG线程确实使用了一个与你们推荐的事件完全一样的事件; 但对我来说仍然听起来像是“跨线程更新UI”。事实上,我的事件在BG线程上触发(因为触发方法只知道这个线程)。但是这个事件会触发一个UI方法(因此也在BG线程上运行),该方法必须然后通过调用“跨越线程”的另一个UI方法。 - Conrad Albrecht

0

Invoke是对象的一个方法,通常在Forms库中的Controls和一些async类中找到。当然,您需要特定的对象才能在该控件/类上调用Invoke。


0
你可能正在尝试从类中调用 Invoke(即不是从 Form 或 Control 中调用)。将代码移出类并放入表单或控件中,你会发现 Invoke 可以编译并正常工作(严格来说,你的代码应该引用 this.Invoke,这样可以清楚地确定方法的来源,但 Invoke 也可以工作,因为它假定了 this)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接