【问题标题】:Invoke looping / crashing调用循环/崩溃
【发布时间】:2014-11-01 18:04:31
【问题描述】:

我想将文本写入文本框。为了能够从不同的线程执行此操作,我调用了一个静态方法,该方法调用了一个包含调用和文本框写入的非静态方法。这样做的时候。我收到错误消息,在设置 Windows 句柄之前它无法调用,所以我正在设置它。我的问题是,

的位置
if (!this.IsHandleCreated)
    this.CreateHandle();

下面的代码是唯一的,我的程序没有崩溃,但现在它只循环(不确定地)BeginInvoke 代码,但实际上不是下面的文本设置代码。我做错了什么?

代码:

private void ActualLog(string input)
        {
            var currentForm = form as Main;

            if (!this.IsHandleCreated)
                this.CreateHandle();
            if (currentForm.txtServerLog.InvokeRequired)
            {
                this.BeginInvoke(new Action<string>(ActualLog), new object[] { input });
                return;
            }
            else
            {
                currentForm.txtServerLog.Text += input + "\r\n";
                currentForm.txtServerLog.Refresh();
            }
        }

        public static void Log(string input)
        {
            Main main = new Main();
            main.ActualLog(input);
        }

在我的帖子中,我会打电话给Log("Any String");

【问题讨论】:

    标签: c# multithreading winforms invoke


    【解决方案1】:

    据我所知,您的无限循环是因为,每当 txtServerLog 将 InvokeRequired 设置为 true 时,您正在调用将 ActualLog 作为操作发送的操作。从本质上讲,每次您走上这条条件路径时,您都会从 ActualLog 重新开始。想象一下,如果你把方法中的所有其他代码都取出来了:

     private void ActualLog(string input)
     {
          ActualLog(input);
     }
    

    我可能在这里遗漏了一些皱纹,但我很确定这正是您在这里所做的。鉴于在 txtServerLog 要求您调用命令的情况下,您无需执行任何操作来更改该状态,因此您将永远循环。

    您想要做的是将您实际尝试调用的函数分离到单独的日志中 - 我假设您的目标是更新 TextBox。

    举个例子:

    private void UpdateTextBox(string input)
    {
        currentForm.txtServerLog.Text += input + "\r\n";
        currentForm.txtServerLog.Refresh();
    }
    

    还有你的 ActualLog 函数:

    private void ActualLog(string input)
    {
        var currentForm = form as Main;
    
        if (!this.IsHandleCreated)
        {
            this.CreateHandle();
        }
        if (currentForm.txtServerLog.InvokeRequired)
        {
            this.Invoke(new Action<string>(UpdateTextBox), new object[] { input }); //Make sure to use Invoke, not BeginInvoke
            return;
        }
    
        UpdateTextBox(input);
    }
    

    请记住,如果您在 if 条件下返回并且没有 else-if,则没有功能上的理由来拥有 else 分支 - 您可以在 if 块之后包含它们。

    关于您传递的代码的一点 - 您实际上并没有在其中调用 Log(),所以我不确定它为什么存在或它是否与您的问题相关。

    【讨论】:

    • @JanH。我不能 100% 确定您要做什么,但我在上面提供了一个示例。
    • 谢谢!在您的示例中使用 Invoke 而不是 BeginInvoke 时,它​​可以工作。这两个函数的作用只是让我可以从另一个线程调用 Log(),因为在静态函数中不允许调用(所以我只是将它放在非静态函数中并从静态函数调用它)。不过还是谢谢 :)
    • @JanH。啊,我花在 WPF 上的时间比 WinForms 多,所以我对 Invoke/BeginInvoke 的区别有点生疏。很高兴听到它有帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-09
    • 2014-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多