【问题标题】:Invoke Control with BackGroundWorker使用 BackGroundWorker 调用控件
【发布时间】:2015-01-04 03:19:38
【问题描述】:

有一个奇怪的问题,无法解决。

尝试在我的应用程序中将 RichTextBox 转换为日志“控制台”。当然,我在我的应用程序中使用线程,当然我知道 Invoke。

让我们看看我的代码。

MainForm 启动一个BackGroundWorker 来完成这项工作。我的BackGroundWorker 在事件中启动了很多调用DebugConsole 的线程。对于这个问题,我举一个简单的例子。

bkw.DoWork += (obj, a) => DebugConsole.DoSomeWork(msg, Color.Coral);
bkw.RunWorkerAsync(); 

DebugConsole 是一个类,我在其中实现了一个单例模式来获取我的DoSomeWork 函数。

我们来看DebugConsole类:

class DebugConsole
{
        private static readonly DebugConsole instance = new DebugConsole();

        public static DebugConsole Instance
        {
            get { return instance; }
        }

        public static void DoSomeWork(string msg, Color color)
        {
            Instance.DebugBox(msg, color);
        }

        private void DebugBox(string msg, Color color)
        {
            MainForm.DoSomeWork(msg, color);
        }
    }

您还看到我的MainForm 也实现了调用下一个思考的单例模式。

private static readonly MainForm instance = new MainForm();

public static MainForm Instance
{
    get { return instance; }
}

public static void DoSomeWork(string ev, Color clr)
{
    Instance.LogTextEvent(ev,clr);
}

LogTextEvent 在我的应用程序中做最后的思考,它在我的 RichTextBox 中写入一条消息,这就是问题所在。它不会写入/调用我的控件。

public void LogTextEvent(string eventText, Color textColor)
{
        var nDateTime = DateTime.Now.ToString("hh:mm:ss tt") + " - ";
        if (rtbDebug.InvokeRequired)
        {
            rtbDebug.BeginInvoke((MethodInvoker) delegate
            {
                rtbDebug.SelectionStart = rtbDebug.Text.Length;
                rtbDebug.SelectionColor = textColor;

                if (rtbDebug.Lines.Length == 0)
                {
                    rtbDebug.AppendText(nDateTime + eventText);
                    rtbDebug.ScrollToCaret();
                    rtbDebug.AppendText(Environment.NewLine);
                }
                else
                {
                    rtbDebug.AppendText(nDateTime 
                                      + eventText 
                                      + Environment.NewLine);
                    rtbDebug.ScrollToCaret();
                }
            });
        }
        else
        {
            rtbDebug.SelectionStart = rtbDebug.Text.Length;
            rtbDebug.SelectionColor = textColor;

            if (rtbDebug.Lines.Length == 0)
            {
                rtbDebug.AppendText(nDateTime + eventText);
                rtbDebug.ScrollToCaret();
                rtbDebug.AppendText(Environment.NewLine);
            }
            else
            {
                rtbDebug.AppendText(nDateTime 
                                  + eventText 
                                  + Environment.NewLine);
                rtbDebug.ScrollToCaret();
            }
        }
    }

问题:我无法控制任何事情。

  • 我做错了什么?
  • 谁能告诉我我错过了什么?

【问题讨论】:

  • 您是否使用过 Visual Studio 调试器来找出实际执行的代码?
  • 当然我用VS来调试...所有代码似乎都可以正常工作
  • Given:你的代码没有做你想做的事,而当你调试它似乎在做你想做的事时,一定是你没有正确调试问题(即误用调试器,从而无法识别错误)。当然,如果没有完整的代码示例,任何人都无法代表您进行任何调试。我在您发布的代码中看到的最大问题是用于调用的复制/粘贴。但在这种情况下,没有任何迹象表明实际问题。您需要improve the code example 或改进您的调试。 :)
  • 您可能正在使用过多的 BeginInvoke() 调用来烧毁 UI 线程。你会看到它燃烧 100% 的核心,试图跟上但没有成功。它不再处理优先级较低的任务,例如绘画。除了降低 BeginInvoke 调用率之外,限制 RTB 中的文本量也非常重要。一段时间后,那些 AppendText() 调用变得非常昂贵。

标签: c# multithreading winforms singleton invoke


【解决方案1】:

试试这个

this.Invoke((MethodInvoker)delegate
        {
             Instance.LogTextEvent(ev,clr);
        });

【讨论】:

  • LogTextEvent 的实现将其编组到 UI 线程以供其实现。
猜你喜欢
  • 1970-01-01
  • 2011-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多