在backgroundworker中从循环更新文本框

时间:2017-03-15 12:04:03

标签: c# 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线程(显然)。如果有人发现了类似的问题,并提供了一些有用的提示,可以直接开始使用这个多线程主题或任何有关我的问题的有用提示,那将非常感激。 来自柏林的致敬, 克里斯

更新:使用以下尝试:

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<decimal>(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();
    }

从那里我得到一个十进制输出,我不断更新,仍然能够利用其他按钮。

2 个答案:

答案 0 :(得分:3)

将循环代码外包给方法。在方法内部,您需要使用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

创建一个Thread并在单击button3时使用新方法启动它

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();
}

在按钮点击事件中启动工作人员:

private void button1_Click(object sender, EventArgs e)
{
    worker.RunWorkerAsync();
}

结果相同:)

答案 1 :(得分:0)

您可能需要查看此链接MSDN

但是,快速提示是为DoWork事件注册方法,然后执行RunAsynchronously方法。