【问题标题】:Looping and appending text to StringBuilder issue循环并将文本附加到 StringBuilder 问题
【发布时间】:2018-08-18 23:58:49
【问题描述】:

我在尝试将循环中的文本附加到字符串生成器时遇到了一个小问题,在尝试了一些事情之后,我认为我在正确的轨道上。

代码:

private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
    // STRING VALUE IT SO WE CAN REUSE //
    string action = e.Argument as string;

    // CONNECTION //
    if (action == "wraith_create_project")
    {

        // STRING BUILDER //
        StringBuilder sb = new StringBuilder();

        // VARS //
        var articleSource = "";

        // INVOKE - AVOID CROSS THREAD ERRORS //
        Invoke(new MethodInvoker(() => { articleSource = comboBoxArticleSources.Text; }));

        // TRY/CATCH //
        try
        {
            // INVOKE - AVOID CROSS THREAD ERRORS //
            Invoke(new MethodInvoker(() => { listBoxMain.Items.Add("[" + DateTime.Now + "] Creating project ... " + txtBoxProjectName.Text); }));

            // ARTICLE SOURCE //
            if (articleSource == "Internal Article Builder")
            {

                // VARS/CONSTANTS //
                var separator             = Environment.NewLine;
                const string gsaSeparator = "\x01";

                // WHICH SPINNER TO USE //
                if (chkBoxInternalSpinner.Checked) {

                    // LOOP //
                    var title = "";
                    var body  = "";
                    var hash  = "";
                    //var gsaArticleInfo = "";

                    for (int x = 0; x <= 5; x++ ) {

                        // EVERY LOOP REQUESTS AN ARTICLE //
                        var requestArticles = Helpers.getArticleTitleAndBodyInternalSpinner("https://www.wraithseo.com/api.php?articleBuilder=1&q=" + txtBoxScrapeKeyword.Text.Replace(" ", "_"));

                        title = Helpers.internalSpinner(requestArticles.Item1); // SEND TO INTERNAL SPINNER FOR SPINNING ...
                        body  = Helpers.internalSpinner(requestArticles.Item2); // SEND TO INTERNAL SPINNER FOR SPINNING ...
                        hash  = To32BitFnv1aHash(body).ToString("X8");

                        Invoke(new MethodInvoker(() =>
                        {
                            listBoxMain.Items.Add("[" + DateTime.Now + "] Returned article ... " + requestArticles.Item1);
                            listBoxMain.Items.Add("[" + DateTime.Now + "] Spun the article ... " + title);
                        }));

                        // ENCODE WITH THE GSA SEPERATOR BETWEEN EACH FIELD //
                        var gsaArticleInfo = title + gsaSeparator + "%first_paragraph-article%"  + gsaSeparator + body + gsaSeparator + hash;

                        // ADD TO THE RICHTEXTBOX ALL FIELDS FROM ABOVE //
                        var richTextBoxText = string.Join(separator, gsaArticleInfo);

                        // APPEND FIELDS TO THE STRINGBUILDER //
                        sb.Append(richTextBoxText);

                    }

                    // INVOKE - AVOID CROSS THREAD ERRORS //
                    Invoke(new MethodInvoker(() => { richTxtBoxArticle.Text = sb.ToString(); }));

                } 

            } else if (articleSource == "") {
                   // RESERVED FOR ADDITIONAL SOURCES //                    
            }

        } catch (Exception ex) {
            Helpers.returnMessage(ex.ToString());
        }
    }
}

我在这里所做的是向我的服务器发送一个请求,该请求返回一个文章大小的一堆文本,然后我旋转该文本并尝试在richTextBox 中显示它,我注意到不是添加每篇文章到richTextBox,它被同一篇文章覆盖,我想通过使用stringbuilder在每个循环上将文章附加到它,然后我可以在循环外显示它,但它似乎总是被覆盖,而不是添加5篇文章(这是我为测试设置的最大值)

任何帮助将不胜感激。

更新代码:

    private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
    {

        string action = e.Argument as string;

        if (action == "wraith_create_project")
        {

            StringBuilder sb = new StringBuilder();

            var separator = Environment.NewLine;
            const string gsaSeparator = "\x01";

            var articleSource = "";
            var title = "";
            var body = "";
            var hash = "";
            var gsaArticleInfo = "";
            var richTextBoxText = "";

            // TEST //
            List<string> gsaStuff = new List<string>();
            // TEST //

            Invoke(new MethodInvoker(() => { articleSource = comboBoxArticleSources.Text; }));

            try
            {
                Invoke(new MethodInvoker(() => { listBoxMain.Items.Add("[" + DateTime.Now + "] Creating project ... " + txtBoxProjectName.Text); }));

                if (articleSource == "Internal Article Builder")
                {

                    if (chkBoxInternalSpinner.Checked) {

                        for (int x = 0; x <= 5; x++ ) {

                            // EVERY LOOP REQUESTS AN ARTICLE WHICH IS RETURNED AT RAND() //
                            var requestArticles = Helpers.getArticleTitleAndBodyInternalSpinner("https://www.wraithseo.com/api.php?articleBuilder=1&q=" + txtBoxScrapeKeyword.Text.Replace(" ", "_"));

                            title = Helpers.internalSpinner(requestArticles.Item1); // SEND TO INTERNAL SPINNER FOR SPINNING ...
                            body  = Helpers.internalSpinner(requestArticles.Item2); // SEND TO INTERNAL SPINNER FOR SPINNING ...
                            hash  = To32BitFnv1aHash(body).ToString("X8");

                            Invoke(new MethodInvoker(() =>
                            {
                                listBoxMain.Items.Add("[" + DateTime.Now + "] Returned article ... " + requestArticles.Item1);
                                listBoxMain.Items.Add("[" + DateTime.Now + "] Spun the article ... " + title);
                            }));

                            // ENCODE WITH THE GSA SEPERATOR BETWEEN EACH FIELD //
                            gsaArticleInfo = title + gsaSeparator + "%first_paragraph-article%"  + gsaSeparator + body + gsaSeparator + hash;

                            // ADD TO THE RICHTEXTBOX ALL FIELDS FROM ABOVE //
                            richTextBoxText = string.Join(separator, gsaArticleInfo);

                            // APPEND FIELDS TO THE STRINGBUILDER //
                            sb.Append(string.Join(separator, gsaArticleInfo));

                            gsaStuff.Add(richTextBoxText);

                            // INVOKE - AVOID CROSS THREAD ERRORS //
                            Invoke(new MethodInvoker(() => { richTxtBoxArticle.AppendText(richTextBoxText); }));
                            Invoke(new MethodInvoker(() => { richTxtBoxArticle.Lines = gsaStuff.ToArray(); }));

                        } // End for loop.

                        Invoke(new MethodInvoker(() => { richTxtBoxArticle.Lines = gsaStuff.ToArray(); }));
                        //Helpers.returnMessage("SB Contents: > " + sb.ToString());

                    } // End checkbox.

                } else if (articleSource == "") {
                       // RESERVED FOR ADDITIONAL SOURCES //                    
                }

            } catch (Exception ex) {
                Helpers.returnMessage(ex.ToString());
            }

        }
    }

【问题讨论】:

  • 是不是像richTxtBoxArticle.Text +=而不是=那么简单?
  • 我没有看到在您的 for 循环中检索到的文章在每次迭代中会有所不同;你没有在任何地方使用x。传递给Helpers.getArticleTitleAndBodyInternalSpinner() 的URL 是否应该改变?您的 articleBuilder 查询参数的值可能不同,而不是固定在 1
  • 做一件事让你作为程序员的生活更轻松——永远不要写catch (Exception ex)。您应该只捕获您可以有意义地处理特定异常。如果您只是记录错误,那么您就是在隐藏错误,并且很难让您的代码 100% 正确。
  • 您也不能在后台工作人员内部调用chkBoxInternalSpinner.CheckedtxtBoxScrapeKeyword.Text,而不在.Invoke 上调用它们。您无法从非 UI 线程安全地创建、更新和读取任何 UI 控件。
  • 我已经用我尝试过的更多东西更新了 OP,这是一个奇怪的东西,richTxtBoxArticle.Text += 似乎不起作用,richTxtBoxArticle.AppendText(richTextBoxText); 它也一直覆盖richTextBox 内容而不是附加到它,我什至尝试了List&lt;string&gt; gsaStuff = new List&lt;string&gt;(); 相同的输出,它总是被覆盖,URL 向服务器发送请求,服务器将返回随机文章(使其每次都是唯一的)我可以在我的日志中看到它这样做,这是意图。

标签: c# winforms for-loop stringbuilder


【解决方案1】:

发生这种情况是因为您正在从另一个线程非常快速地调用 UI 线程。文本框根本跟不上。

这里的解决方案是使用BackgroundWorker.ReportProgress 方法,并将字符串从您的工作线程传回您的UI 线程。您将从表单中处理工作人员的 ProgressChanged 事件,并在其中更新您的控件。

希望对你有所帮助。

【讨论】:

    猜你喜欢
    • 2018-09-22
    • 1970-01-01
    • 2014-11-12
    • 1970-01-01
    • 2013-11-30
    • 2017-02-16
    • 2017-01-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多