C# 未通过BackgroundWorker在启用DataReceiveDevenHandler的情况下实时更新文本框
我需要一些后台工作人员的帮助。使用Visual Studio 2015及其windows窗体 我是这类事情的新手,真的不知道它是如何工作的等等。到目前为止,我的代码是基于这里的各种帖子 工人没有被解雇,但不知道为什么。我相信这与datarcievedeventhandler有关,因为当我移动时,如果我移动worker.DoWork+=worker\u DoWork\uux;和worker.RunWorkerAsync();在点击按钮的事件中,禁用DataReceivedEventHandler,方法worker_DoWork_被激发,我可以用DoSomeWork下分配的任何静态文本更新textBox 另外,我不知道如何通过DoSomeWork将大纲数据传递到文本框中 有人能帮忙吗C# 未通过BackgroundWorker在启用DataReceiveDevenHandler的情况下实时更新文本框,c#,multithreading,backgroundworker,C#,Multithreading,Backgroundworker,我需要一些后台工作人员的帮助。使用Visual Studio 2015及其windows窗体 我是这类事情的新手,真的不知道它是如何工作的等等。到目前为止,我的代码是基于这里的各种帖子 工人没有被解雇,但不知道为什么。我相信这与datarcievedeventhandler有关,因为当我移动时,如果我移动worker.DoWork+=worker\u DoWork\uux;和worker.RunWorkerAsync();在点击按钮的事件中,禁用DataReceivedEventHandler,
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
}
}
}问题在于您概述了
RunWorkerAsync()代码>。此方法触发处理异步代码的DoWork事件。通过DoWork的EventArgs,您可以将结果重用回主线程,并将其打印到文本框中。您可以在RunWorkerCompleted事件中获得结果。下面是一个基于您的代码的小示例:
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();
}
}
}
此外,您可能会对哪种方法更容易处理线程感兴趣
更新:
你说:
我想实时更新我的文本框
这将在文本框中直接打印批处理文件发送到Standardoutput的文本。所以我觉得你不再需要了
private void OutputHandler(object sendingProcess, DataReceivedEventArgs e)
{
if (!string.IsNullOrWhiteSpace(e.Data))
BeginInvoke(new MethodInvoker(() => { textBox1.Text = e.Data; }));
}
多亏了@Sebi,我成功地解决了所有问题。事实证明,我不需要像一些人所建议的那样有一个后台工作人员
请参见最终代码,其工作原理类似于符咒:
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); }));
}
}
}
}为什么要对//worker.RunWorkerAsync();?进行注释;???因为我得到一个异常错误,说Backgroundworker已经在运行,不能同时运行。因此,我认为DataReceivedHandler踢了其中一个,但我可能错了,您需要取消注释该行。如果您尝试再次运行它,它就会崩溃。因此,首先,检查(!worker.IsBusy){worker.RunWorkerAsync();}-这将只允许它在当前未运行时运行。酷工作了。然而。我的文本框仅在CMD完成运行后更新。我需要实时更新它。此外,似乎每次从CMD接收数据时,该方法只调用一次。谢谢,但我的文本框没有实时更新,即每次将一行插入CMD窗口时。它只输出“完成!”。知道为什么吗?@TomPisz我不清楚你的目标。如果调用worker.RunWorkerAsync();这将恰好运行一次您的嫁妆活动。因此,可以肯定的是,它的结果是一次成功!在我的例子中。请注意,Backgroundworker并不意味着实时做某事。它只是让你在长时间运行的操作上有一个响应用户界面的能力。对不起,Sebi,但这是我在各种网站和论坛上找到的。我需要实时更新文本框,有人建议使用backgrounder。我对C#和这类事件不太熟悉,所以不太确定如何做,只是尝试和错误的方法。“你能给我指出正确的方向吗?”汤姆皮兹我更新了我的答案。我不确定你是否理解正确。谢谢。你完全理解我。CMD输出需要实时重定向到文本框。有了你们更新的答案,我得到了跨线程异常错误,我想这是我使用backgrounder的原因。希望这是有意义的。