【问题标题】:C# cross-thread call problemC#跨线程调用问题
【发布时间】:2011-04-28 08:44:34
【问题描述】:

我正在用 c# 编写一个表单应用程序,我需要能够从任何线程更改富文本框的内容,我尝试使用 delegateInvokeRequired,但是我创建的委托仍然给我一个跨线程调用错误,并且 InvokeRequired 使表单崩溃,而没有给出错误。 我需要能够从任何线程执行的函数:

    public static void updateSub(int what)
    {
        subDisplay.subBox.Text = tb[what];
    }

我尝试使用的委托:

    public delegate void UpdateDelegateVoid(int what);
    static public UpdateDelegateVoid uSub = new UpdateDelegateVoid(updateSub);
    uSub(0);

我的 InvokeRequired 代码:

    public static void updateSub(int what)
    {
        if (subDisplay.subBox.InvokeRequired)
        {
            subDisplay.subBox.Invoke(new MethodInvoker(finish));
        }
        else
        {
            subDisplay.subBox.Text = tb[what];
        }
    }

我不太确定为什么上面的代码不起作用。谢谢!

【问题讨论】:

  • 抱歉,finish 是什么? MethodInvoker 是什么?
  • subDisplay.subBox.Invoke(new MethodInvoker(finish)) 这个位是做什么的,为什么它在静态方法中,当然它应该在subDisplay 的实例上。 subDisplay 是静态属性吗?
  • @Martinho:MethodInvoker 一直存在到 .Net 1.1,并且在 Action 出现之前使用。
  • 要更接近发生异常的点,您应该在 Visual Studio 中打开 Debug - Exceptions 并选中所有复选框。在这种情况下,编译器将在抛出异常之前中断。

标签: c# winforms delegates multithreading invokerequired


【解决方案1】:

严格来说,当您检查InvokeRequired 并发现它是true 时,您应该将调用编组到相同的方法。我不确定它是否能解决您的具体问题(我需要查看更多异常详细信息和代码),但这就是我的意思:

public static void updateSub(int what)
{
    if (subDisplay.subBox.InvokeRequired)
    {
        subDisplay.subBox.Invoke(new Action<int>(updateSub), what);
    }
    else
    {
        subDisplay.subBox.Text = tb[what];
    }
}

如果您遇到“奇怪的行为”,请检查该表单是否实际上是在主应用程序线程上创建的。在 WinForms 中,这不是强制的(就像在 WPF 中一样),因此创建表单的线程可能实际上不是应用程序的根线程。

【讨论】:

  • 但这行不通。 MethodInvoker 是一个委托,用于调用没有参数和返回值的方法。但是 updateSub 有一个 int 参数...
  • @Neil Umm,MethodInvoker '崩溃'表单的原因是我不小心放了 MethodInvoker(finish) 而不是 MethodInvoker(updateSub),我认为如果我改变它会起作用.. . 虽然,我找到了一种进行有效跨线程调用的方法:`displaySub.Invoke((MethodInvoker)delegate { subDisplay.subBox.Text = tb[what]; });`
  • @George:所以,您实际上并没有遇到跨线程错误,对吧?
  • @takrl 好点,以及为什么应该内置编译器。 :) 我已经更新为通用的Action
  • @Martinho:我在使用委托时遇到了跨线程错误,尽管我在使用 MethodInvoke 时遇到的“表单崩溃”只是我的愚蠢造成的……:)跨度>
【解决方案2】:

我主要使用这个,而且效果很好。出于完全相同的目的是您的意图。

public void UpdateSub(string message)
{
    subDisplay.subBox.Invoke((Action)delegate {
        subDisplay.subBox.Text = message;
    });
}

希望它对您或其他人有所帮助!

【讨论】:

    【解决方案3】:

    试试这个 - 如果需要调用,您可以调用相同的方法。

    public void UpdateSub(string message)
    {
        if (!subDisplay.subBox.InvokeRequired)
        {
            subDisplay.subBox.Text = message;
        }
        else
        {
            var d = new UpdateFormText(UpdateSub);
            Invoke(d, new object[] { message });
        }
    }
    

    UpdateFormText 是委托

    public delegate void UpdateFormText(string message);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-06
      • 1970-01-01
      • 1970-01-01
      • 2010-10-02
      相关资源
      最近更新 更多