gpt4 book ai didi

c# - 通过 C# 更新 UI 线程(文本框)

转载 作者:太空狗 更新时间:2023-10-29 23:02:06 25 4
gpt4 key购买 nike

这里的商业智能人员掌握了足够多的 C# 知识,这很危险。

我构建了一个自制的 winforms 应用程序,它本质上是在循环中执行命令行工具来“做事”。所说的东西可能会在几秒钟或几分钟内完成。通常我需要为 DataTable 中的每一行执行一次该工具。

我需要重定向命令行工具的输出并将其显示在“我的”应用程序中。我正在尝试通过文本框这样做。我遇到了有关更新 UI 线程的问题,我自己无法解决这些问题。

为了执行我的命令行工具,我从这里借用了代码:How to parse command line output from c#?

这是我的等价物:

        private void btnImport_Click(object sender, EventArgs e)
{
txtOutput.Clear();
ImportWorkbooks(dtable);

}


public void ImportWorkbooks(DataTable dt)
{

ProcessStartInfo cmdStartInfo = new ProcessStartInfo();
cmdStartInfo.FileName = @"C:\Windows\System32\cmd.exe";
cmdStartInfo.RedirectStandardOutput = true;
cmdStartInfo.RedirectStandardError = true;
cmdStartInfo.RedirectStandardInput = true;
cmdStartInfo.UseShellExecute = false;
cmdStartInfo.CreateNoWindow = false;

Process cmdProcess = new Process();
cmdProcess.StartInfo = cmdStartInfo;
cmdProcess.ErrorDataReceived += cmd_Error;
cmdProcess.OutputDataReceived += cmd_DataReceived;
cmdProcess.EnableRaisingEvents = true;
cmdProcess.Start();
cmdProcess.BeginOutputReadLine();
cmdProcess.BeginErrorReadLine();

//Login
cmdProcess.StandardInput.WriteLine(BuildLoginString(txtTabCmd.Text, txtImportUserName.Text, txtImportPassword.Text, txtImportToServer.Text));


foreach (DataRow dr in dt.Rows)
{
cmdProcess.StandardInput.WriteLine(CreateServerProjectsString(dr["Project"].ToString(), txtTabCmd.Text));

//Import Workbook

cmdProcess.StandardInput.WriteLine(BuildPublishString(txtTabCmd.Text, dr["Name"].ToString(), dr["UID"].ToString(),dr["Password"].ToString(), dr["Project"].ToString()));
}
cmdProcess.StandardInput.WriteLine("exit"); //Execute exit.
cmdProcess.EnableRaisingEvents = false;
cmdProcess.WaitForExit();
}


private void cmd_DataReceived(object sender, DataReceivedEventArgs e)
{
//MessageBox.Show("Output from other process");
try
{
// I want to update my textbox here, and then position the cursor
// at the bottom ala:

StringBuilder sb = new StringBuilder(txtOutput.Text);
sb.AppendLine(e.Data.ToString());
txtOutput.Text = sb.ToString();
this.txtOutput.SelectionStart = txtOutput.Text.Length;
this.txtOutput.ScrollToCaret();


}
catch (Exception ex)
{
Console.WriteLine("{0} Exception caught.", ex);

}

}

当我在 cmd_DataReceived () 中实例化我的 StringBuilder 时引用 txtOuput.text 会导致应用挂起:我猜是某种跨线程问题。

如果我在 StringBuilder 中删除对 txtOuput.text 的引用并继续调试,我会在此处遇到跨线程违规:

txtOutput.Text = sb.ToString();

Cross-thread operation not valid: Control 'txtOutput' accessed from a thread other than the thread it was created on.

好吧,不奇怪。我假设 cmd_DataReceived 正在另一个线程上运行,因为我是在 Process.Start() 之后做的事情而击中它的……如果我删除 cmd_DataReceived() 中对 txtOuput.Text 的所有引用并简单地转储命令行文本通过 Console.Write() 输出到控制台,一切正常。

因此,接下来我将尝试使用 http://msdn.microsoft.com/en-us/library/ms171728.aspx 中的信息在 UI 线程上更新我的 TextBox 的标准技术。

我在我的类中添加了一个委托(delegate)和线程:

delegate void SetTextCallback(string text);
// This thread is used to demonstrate both thread-safe and
// unsafe ways to call a Windows Forms control.
private Thread demoThread = null;

我添加了一个程序来更新文本框:

 private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.txtOutput.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.txtOutput.Text = text;
}
}

我添加了另一个调用线程安全的过程:

 private void ThreadProcSafe()
{
// this.SetText(sb3.ToString());
this.SetText("foo");

}

...最后我在 cmd_DataReceived 中这样称呼这个困惑:

private void cmd_DataReceived(object sender, DataReceivedEventArgs e)
{
//MessageBox.Show("Output from other process");
try
{

sb3.AppendLine(e.Data.ToString());

//this.backgroundWorker2.RunWorkerAsync();
this.demoThread = new Thread(new ThreadStart(this.ThreadProcSafe));
this.demoThread.Start();
Console.WriteLine(e.Data.ToString());

}
catch (Exception ex)
{
Console.WriteLine("{0} Exception caught.", ex);


}

}

…当我运行这段文字时,文本框像门钉一样呆在那里,没有得到更新。我的控制台窗口继续更新。如您所见,我尝试通过让文本框显示“foo”与工具的实际输出来稍微简化一些事情——但没有任何乐趣。我的 UI 已死。

那么是什么给了?无法弄清楚我做错了什么。我一点也不喜欢在文本框中显示结果,顺便说一句 - 我只需要能够看到应用程序内部发生了什么,我不想弹出另一个窗口来这样做。

非常感谢。

最佳答案

我认为问题出在这一行:

cmdProcess.WaitForExit(); 

它在 ImportWorkbooks 方法中,该方法从 btnImport 的 Click 事件方法中调用。因此,您的 UI 线程将被阻塞,直到后台进程完成。

关于c# - 通过 C# 更新 UI 线程(文本框),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8269823/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com