【问题标题】:TextBox not updated in real time via BackgroundWorker with DataReceivedEventHandler enabled文本框未通过启用 DataReceivedEventHandler 的 BackgroundWorker 实时更新
【发布时间】:2017-01-10 19:27:44
【问题描述】:

我需要一些有关 BackgroundWorker 的帮助。使用 Visual Studio 2015 及其 windows 窗体

我是这种东西的新手,真的不知道它是如何工作的等等。我到目前为止的代码是基于这里的各种帖子。

worker_DoWork_ 根本没有被解雇,但不知道为什么。我相信这与 DataRceivedEventHandler 有关,因为当我移动 If 我移动 worker.DoWork += worker_DoWork_;和 worker.RunWorkerAsync();进入按钮单击事件并禁用 DataReceivedEventHandler,方法 worker_DoWork_ 被触发,我可以使用 DoSomeWork 下分配的任何静态文本更新 textBox。

另外,我不知道如何通过 DoSomeWork 将大纲数据传递到文本框中。

有人可以帮忙吗。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;


namespace CMD_testing
{
  public partial class Form1 : Form
  {
    BackgroundWorker worker;
    private delegate void DELEGATE();

    public Form1()
    {
        InitializeComponent();
        worker = new BackgroundWorker();
    }

    private void button2_Click(object sender, EventArgs e)
    {

        Process process;
        process = new Process();
        process.StartInfo.FileName = @"C:\\Project\Test\Data.bat";
        process.StartInfo.UseShellExecute = false;
        //   process.StartInfo.CreateNoWindow = true;
        process.StartInfo.RedirectStandardOutput = true;
        process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);

        process.StartInfo.RedirectStandardInput = true;
        process.Start();
        process.BeginOutputReadLine();
       // process.WaitForExit();
        // process.Close();
    }

    private void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
    {
        if (outLine.Data != null)
        {
            Console.WriteLine("Im here...");

            worker.DoWork += worker_DoWork_;
            //worker.RunWorkerAsync();
            Console.WriteLine("Im here NOW");

            Console.WriteLine(outLine.Data);  //its outputed fine into the console 
        }

    }

    private void worker_DoWork_(object sender, DoWorkEventArgs e)
    {
        Console.WriteLine("I'm at worker_DoWork_");
        Delegate del = new DELEGATE(DoSomeWork);
        this.Invoke(del);
    }

    private void DoSomeWork()
    {
        Thread.Sleep(1000);
        textBox1.Text = "????";  // how to pass outline.Data in here

    }

}

}

【问题讨论】:

  • 为什么评论了 //worker.RunWorkerAsync();???
  • 因为我收到异常错误提示 Backgroundworker 已经在运行并且无法同时运行。因此,我相信 DataReceivedHandler 是其中之一,但我可能错了
  • 您需要取消注释该行。如果您尝试第二次运行它,那么它将崩溃。所以首先,检查 if (!worker.IsBusy) { worker.RunWorkerAsync(); } - 只有在当前未运行时才允许它运行。
  • 很酷。然而。我的文本框仅在 CMD 完成运行后更新。我需要实时更新它。此外,似乎该方法只调用一次,而不是每次从 CMD 接收数据时调用。

标签: c# multithreading backgroundworker


【解决方案1】:

问题是你勾勒出RunWorkerAsync();。此方法触发处理异步代码的 DoWork-Event。通过 DoWork 的 EventArgs,您可以将结果重用回您的主线程并将其打印到您的文本框。您可以在 RunWorkerCompleted-Event 中获得结果。这是一个基于您的代码的小示例:

  public partial class Form1 : Form
  {
    BackgroundWorker worker;

    public Form1()
    {
        InitializeComponent();
        worker = new BackgroundWorker();
        worker.DoWork += worker_DoWork;
        worker.RunWorkerCompleted += worker_Completed;
    }

    private void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
    {
        if (outLine.Data != null)
        {
            if (!worker.IsBusy) //Check if Worker is working and avoid exception
               worker.RunWorkerAsync();     
        }
    }

    private void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        //Process some Long-Running Task
        Thread.Sleep(5000)
        e.Result = "Done!";
    }

    private void worker_Completed(object sender, RunWorkerCompletedEventArgs e)
    {
       textbox.Text = e.Result.ToString();
    }
  }
}

此外,您可能对Task Library 感兴趣,它使线程的处理更容易。

更新:

你说:

我想实时更新我的​​文本框。

这将在您的文本框中直接打印您的批处理文件发送到 Standardoutput 的文本。所以我认为你不再需要了。

private void OutputHandler(object sendingProcess, DataReceivedEventArgs e)
    {
        if (!string.IsNullOrWhiteSpace(e.Data))
           BeginInvoke(new MethodInvoker(() => { textBox1.Text = e.Data; }));
    }

【讨论】:

  • 谢谢,但我的文本框没有实时更新,即每次在 cmd 窗口中插入一行。它只输出“完成!”。知道为什么吗?
  • @TomPisz 我不清楚你的目标。如果你调用 worker.RunWorkerAsync();这将完全运行您的 DoWork-Event 一次。所以肯定它会导致一个完成!在我的例子中。请注意,Backgroundworker 并不意味着实时做某事。它只是让您能够在长时间运行的操作中使用响应式 UI。
  • 对不起 Sebi,但这是我在各种网站和论坛上找到的。我需要实时更新文本框,有人建议使用后台程序。我是 C# 和这种事件的新手,所以不太清楚如何去做,只是简单地尝试和错误方法。你能指出我正确的方向吗?
  • @TomPisz 我更新了我的答案。我不太确定是否以正确的方式理解您。
  • 谢谢。你正确地理解了我。 CMD 输出需要实时重定向到 textBox 中。有了您更新的答案,我收到了跨线程异常错误,我认为这是我使用后台程序的原因。希望这是有道理的。
【解决方案2】:

感谢@Sebi,我已经设法解决了所有问题。事实证明,我不需要像某些人建议的那样使用 BackgroundWorker。

看看最终的代码,它就像一个魅力:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;


namespace CMD_testing
{
    public partial class Form1 : Form
    {
    public Form1()
    {
        InitializeComponent();
    }

    private void button2_Click(object sender, EventArgs e)
    {

        Process process;
        process = new Process();
        process.StartInfo.FileName = @"C:\\Project\Test\Other Data.bat";
        process.StartInfo.UseShellExecute = false;
          process.StartInfo.CreateNoWindow = true;
        process.StartInfo.RedirectStandardOutput = true;
        process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);

        process.StartInfo.RedirectStandardInput = true;
        process.Start();
        process.BeginOutputReadLine();
        process.Close();
    }

    private void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
    {
        if (outLine.Data != null)
        {
            BeginInvoke(new MethodInvoker(() => { textBox1.AppendText(outLine.Data + Environment.NewLine); }));
        }

    }
  }

}

【讨论】:

    猜你喜欢
    • 2021-12-05
    • 2021-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-03
    • 1970-01-01
    • 1970-01-01
    • 2011-03-06
    相关资源
    最近更新 更多