简体   繁体   中英

Background Worker In Winforms Not Updating TextBox

I am attempting to use a Background Worker in order to add a Cancel button to my winform.

I have added the below syntax, but the textbox is never updated with any progress as it was before I tried to implement the background worker.

public Form1()
{
    AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
    {
        string resourceName = new AssemblyName(args.Name).Name + ".dll";
        string resource = Array.Find(this.GetType().Assembly.GetManifestResourceNames(), element => element.EndsWith(resourceName));

        using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resource))
        {
            Byte[] assemblyData = new Byte[stream.Length];
            stream.Read(assemblyData, 0, assemblyData.Length);
            return Assembly.Load(assemblyData);
        }
    };
    InitializeComponent(); 
    backgroundWorker1.WorkerReportsProgress = true;  
    backgroundWorker1.WorkerSupportsCancellation = true;
}
private void btnQuery_Click(object sender, EventArgs e)
{
    backgroundWorker1.RunWorkerAsync();
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{

        //Iterating the array
        foreach (string s in sxc)
        {
            txt_ProgressDetails.Visible = true;
            AppendTextBoxLine("Getting Data For " + s);

            //Put data into DataTable
            PopulateDT(s);
        }

        //If the cancel button was pressed
        if (backgroundWorker1.CancellationPending)
        {
            e.Cancel = true;
            return;
        }
}

    private void AppendTextBoxLine(string statusMessage)
    {
        if (txt_ProgressDetails.Text.Length > 0)
            txt_ProgressDetails.AppendText(Environment.NewLine);
        txt_ProgressDetails.AppendText(statusMessage);
    }

The Do_Work event of BackgroundWorker runs in a non-STA thread and you can't update UI from there. You can rewrite your code to update UI elements from the thread that created them with InvokeRequred and Invoke method.

Add this to your Form:

delegate void UpdateUICallback(string statusMessage);

And Change your AppendTextBoxLine method to this:

if (InvokeRequired)
{
    UpdateUICallback d = new UpdateUICallback(AppendTextBoxLine);
    this.Invoke(d, new object[] {statusMessage});
}
else
{
    if (txt_ProgressDetails.Text.Length > 0)
            txt_ProgressDetails.AppendText(Environment.NewLine);
    txt_ProgressDetails.AppendText(statusMessage);
}

so your code will look like this:

public Form1()
{
    AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
    {
        string resourceName = new AssemblyName(args.Name).Name + ".dll";
        string resource = Array.Find(this.GetType().Assembly.GetManifestResourceNames(), element => element.EndsWith(resourceName));

        using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resource))
        {
            Byte[] assemblyData = new Byte[stream.Length];
            stream.Read(assemblyData, 0, assemblyData.Length);
            return Assembly.Load(assemblyData);
        }
    };
    InitializeComponent(); 
    backgroundWorker1.WorkerReportsProgress = true;  
    backgroundWorker1.WorkerSupportsCancellation = true;
}
private void btnQuery_Click(object sender, EventArgs e)
{
    backgroundWorker1.RunWorkerAsync();
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{

        //Iterating the array
        foreach (string s in sxc)
        {
            txt_ProgressDetails.Visible = true;
            AppendTextBoxLine("Getting Data For " + s);

            //Put data into DataTable
            PopulateDT(s);
        }

        //If the cancel button was pressed
        if (backgroundWorker1.CancellationPending)
        {
            e.Cancel = true;
            return;
        }
}

delegate void UpdateUICallback(string statusMessage);
private void AppendTextBoxLine(string statusMessage)
{
    if (InvokeRequired)
    {
        UpdateUICallback d = new UpdateUICallback(AppendTextBoxLine);
        this.Invoke(d, new object[] {statusMessage});
    }
    else
    {
        if (txt_ProgressDetails.Text.Length > 0)
                txt_ProgressDetails.AppendText(Environment.NewLine);
        txt_ProgressDetails.AppendText(statusMessage);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM