在backgroundworker中从循环更新文本框
我知道这个问题会被问到一些问题(至少从我到目前为止所发现的问题),但我无法真正理解它。 已经尝试过msdn的例子,但仍然没有成功。 这是我正在尝试做的事情:我有一个连接到TLL标尺的USB计数器。 我想在循环中不断读取值并将读数写入文本框而不阻止主UI。 我从其他问题中知道我应该使用Invoke或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.Runtime.InteropServices; using System.Windows.Forms; namespace USB_Counter { public partial class Form1 : Form { [DllImport("HS_UC.dll", EntryPoint = "HS_UC_Close")] //+further DLL imports (driver for USBCounter) public static extern int HS_UC_Close(int CounterNo); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) //initialize COunter { int A = HS_UC_Init(1, 3); string B = Convert.ToString(A); MessageBox.Show(B); //to check if there is no error } private void button2_Click(object sender, EventArgs e) { HS_UC_SetDistCode(1, 20, 40, 4, 0, 0); //set Reference HS_UC_SetRefMode(1, 1); } private void button3_Click(object sender, EventArgs e) { int a = 1; int A = 0; //variable that takes counter value (the one I want) int B = 0; //variable that takes counter status do { HS_UC_GetCounter(1, ref A, ref B); decimal C = (Convert.ToDecimal(A) / 100); textBox1.Text = "Das ist: " + C; textBox1.Update(); } while (a == 1); } }
}
现在这可以作为用户,但如上所述,它阻止了主UI线程(显然)。 如果有人发现了类似的问题,并提供了一些有用的提示,可以直接开始使用这个multithreading主题或任何有关我的问题的有用提示,那将非常感激。 最诚挚的问候柏林,克里斯
更新:让它与以下尝试一起工作:
private void Counter_Read() { int a = 1; do { int A = 0; int B = 0; HS_UC_GetCounter(1, ref A, ref B); decimal C = (Convert.ToDecimal(A) / 100); UpdateTextBox(C); } while (a == 1); } public void UpdateTextBox(decimal C) { if (InvokeRequired) { this.Invoke(new Action(UpdateTextBox), new object[] { C }); return; } textBox1.Text = "Das ist: " + C; textBox1.Update(); } private void button3_Click(object sender, EventArgs e) { System.Threading.Thread t = new System.Threading.Thread(() => Counter_Read()); t.Start(); }
从那里我得到一个十进制输出,我不断更新,仍然能够利用其他按钮。
将循环代码外包给方法。 在方法内部,您需要使用BeginInvoke
写入TextBox
private void DoTheLoop() { int a = 1; int A = 0; //variable that takes counter value (the one I want) int B = 0; //variable that takes counter status do { HS_UC_GetCounter(1, ref A, ref B); decimal C = (Convert.ToDecimal(A) / 100); textBox1.BeginInvoke(new Action(()=>{textBox1.Text = "Das ist: " + C;})); } while (a == 1); }
使用普通线程的 第一个版本 :
创建一个Thread并在单击button3
时使用new方法启动它
private void button3_Click(object sender, EventArgs e) { System.Threading.Thread t = new System.Threading.Thread(()=>DoTheLoop()); t.Start(); }
这不应该阻止您的GUI,文本框将显示值
使用BackgroundWorker的 第二版 :
创建BackgroundWorker并注册DoWork
事件:
System.ComponentModel.BackgroundWorker worker = new System.ComponentModel.BackgroundWorker(); private void Form1_Load(object sender, EventArgs e) { worker.DoWork += Worker_DoWork; }
在事件处理程序内部调用相同的方法DoTheLoop()
:
private void Worker_DoWork(object sender, DoWorkEventArgs e) { DoTheLoop(); }
在按钮单击事件中启动worker:
private void button1_Click(object sender, EventArgs e) { worker.RunWorkerAsync(); }
结果相同:)
你可能想看看这个链接MSDN 。
但是,快速提示是为DoWork
事件注册一个方法,然后执行RunAsynchronously
方法。