RE: Can't update foreground panel from background thread

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



Hi Greg,
you cannot update a control from a thread that did not create the control.
In your case you are adding the labels to the panel from a different thread
so that is probably why it is not updating automatically. What you want to
do is transfer control back to the main UI thread to update the panel, you
can do this using Invoke, so inside of backgroundWorker1_DoWork, do something
like:

void private void backgroundWorker1_DoWork(.....)
{
//Update panel
UpdatePanel();
}

private void UpdatePanel()
{
if(this.panelTemp.InvokeRequired)
{
//being called from different thread than main UI thread,
//call this function again on the main thread.
this.panelTemp.Invoke(new MethodInvoker(UpdatePanel));
}
else
{
Label label1 = new Label();
label1.Text = "Label 1 text from background thread";
label1.Location = new Point(1, 1);
label1.Size = new Size(200, 35);
panelTemp.Controls.Add(label1);

Label label2 = new Label();
label2.Text = "Label 2 text from background thread";
label2.Location = new Point(1, 15);
label2.Size = new Size(200, 35);
panelTemp.Controls.Add(label2);
}
}

Mark
--
http://www.markdawson.org
"Code like the person who maintains your code is a axe murdered - WHO KNOWS
WHERE YOU LIVE"


"Greg Larsen" wrote:

I'm trying to figure out how to modify a panel (panel1) from a
backgroundworker thread. But can't get the panel to show the new controls
added by the backgroundwork task. Here is my code. In this code there is a
panel panel1, that I populate with a lable in the foreground. Then when I
click on "button1" a backgroundworker thread in async mode is started. When
the backgoundworker thread completes the thread returns a panel to populate
the panel1 control in the form with two controls label1 and lable 2. What I
can't figure out is how to redraw the form, or panel so the two new controls
are displayed. Does anyone know how to change my code to resolve this
problem?

Here is my code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace test
{
class Form1 : Form
{
public Form1()
{
InitializeComponent();
Label label1 = new Label();
label1.Text = "Label 1 text from foreground thread";
label1.Location = new Point(1, 1);
label1.Size = new Size(200, 35);
panel1.Controls.Add(label1);

}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs
e)
{
// Simulate a long-running task by putting the thread
// to sleep a random number of times. Each time the
// thread wakes up, report the progress.
BackgroundWorker worker = (BackgroundWorker)sender;
System.Random rand = new Random();
Panel panelTemp = new Panel();
int max = rand.Next(50, 500);
for (int i = 0; i < max; i++)
{
// Cancel upon cancellation requests
if (worker.CancellationPending)
{
e.Cancel = true;
break;
}
else
{
// Sleep for 30 milliseconds
System.Threading.Thread.Sleep(30);
worker.ReportProgress((int)i * 100 / max);
}
}
// Pass up the number of iterations perform to the main thread

Label label1 = new Label();
label1.Text = "Label 1 text from background thread";
label1.Location = new Point(1, 1);
label1.Size = new Size(200, 35);
panelTemp.Controls.Add(label1);

Label label2 = new Label();
label2.Text = "Label 2 text from background thread";
label2.Location = new Point(1, 15);
label2.Size = new Size(200, 35);
panelTemp.Controls.Add(label2);
e.Result = panelTemp;

}

private void backgroundWorker1_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
backgroundProgressBar.Value = e.ProgressPercentage;



}

private void backgroundWorker1_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
MessageBox.Show(
this,
"Background processing completed with errors: " +
e.Error.Message,
"ERROR!");
else if (e.Cancelled)
MessageBox.Show(
this,
"Background processing cancelled.",
"Cancelled");
else
{
panel1 = (Panel)e.Result;
MessageBox.Show("Number of controls on Panel1 - " +
panel1.Controls.Count.ToString());
panel1.Invalidate();
panel1.Refresh();
}


}

private void button1_Click(object sender, EventArgs e)
{
// Reset progress bar

backgroundProgressBar.Minimum = 0;
backgroundProgressBar.Maximum = 100;
backgroundProgressBar.Value = 0;
panel1.Controls.Clear();
// Initiate asynchronous processing
backgroundWorker1.RunWorkerAsync();

}

private void button2_Click(object sender, EventArgs e)
{

// Cancel asynchronous processing

if (backgroundWorker1.IsBusy)
backgroundWorker1.CancelAsync();


}

private System.ComponentModel.IContainer components = null;

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be
disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}

#region Windows Form Designer generated code

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.backgroundProgressBar = new
System.Windows.Forms.ProgressBar();
this.backgroundWorker1 = new
System.ComponentModel.BackgroundWorker();
this.panel1 = new System.Windows.Forms.Panel();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(24, 30);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(55, 22);
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// button2
//
this.button2.Location = new System.Drawing.Point(136, 30);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(59, 22);
this.button2.TabIndex = 1;
this.button2.Text = "button2";
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// backgroundProgressBar
//
this.backgroundProgressBar.Location = new
System.Drawing.Point(24, 125);
this.backgroundProgressBar.Name = "backgroundProgressBar";
this.backgroundProgressBar.Size = new System.Drawing.Size(229,
23);
this.backgroundProgressBar.TabIndex = 2;
//
// backgroundWorker1
//
this.backgroundWorker1.WorkerReportsProgress = true;
this.backgroundWorker1.WorkerSupportsCancellation = true;
this.backgroundWorker1.DoWork += new
System.ComponentModel.DoWorkEventHandler(this.backgroundWorker1_DoWork);
this.backgroundWorker1.RunWorkerCompleted += new
System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted);
this.backgroundWorker1.ProgressChanged += new
System.ComponentModel.ProgressChangedEventHandler(this.backgroundWorker1_ProgressChanged);
//
// panel1
//
this.panel1.BackColor =
System.Drawing.SystemColors.ControlLightLight;
this.panel1.Location = new System.Drawing.Point(24, 177);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(238, 50);
this.panel1.TabIndex = 3;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.Add(this.panel1);
this.Controls.Add(this.backgroundProgressBar);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);

}

#endregion

private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.ProgressBar backgroundProgressBar;
private System.ComponentModel.BackgroundWorker backgroundWorker1;
private System.Windows.Forms.Panel panel1;
}
}


.



Relevant Pages

  • RE: Cant update foreground panel from background thread
    ... to the UI thread and update the panel1 control. ... In your case you are adding the labels to the panel from a different thread ... void private void backgroundWorker1_DoWork ... Label label1 = new Label; ...
    (microsoft.public.dotnet.languages.csharp)
  • RE: Cant update foreground panel from background thread
    ... control collection so it was never being shown. ... /// The camera that the video canvas is displaying ... In your case you are adding the labels to the panel from a different thread ... void private void backgroundWorker1_DoWork ...
    (microsoft.public.dotnet.languages.csharp)
  • Problem Locating Controls Within a Panel With A Vertical Scroll Bar
    ... I have found that locating, i.e. placing, controls within a Panel which has a vertical scroll bar results in eratic locations. ... It seems that so long as the slider is at the top there is no problem, but if the slider is at the bottom when the Controls.Add is done the control does not end up where its Location property specifies. ... Each time you click on the Add button another Label is added. ... Private Sub Form1_LoadHandles MyBase.Load ...
    (microsoft.public.dotnet.languages.vb)
  • Re: Transparents LAbel
    ... Container ist, kann Transparent auch nicht auf das Steuerelement angewendet werden, somit bleibt der Container übrig in dem sich die Steuerelemente befinden. ... Wenn es sich nur um eine Balkenzeige handelt, so kannst Du diese doch relativ schnell realisieren, in dem Du Dir ein eigenes Control erstellst. ... Genauso könntest Du das Control und ein Label in ein Panel verpacken, wo das Label erscheinst, da setzt Du einfach über die Dock-Eigenschaften der Controls fest. ... Panel aufs Formular ...
    (microsoft.public.de.german.entwickler.dotnet.vb)
  • Re: Error in update: Windows Genuine Advantage Notification (KB905
    ... Can't remove the update with Add/Remove programs in control ... panel as update KB905474 for WGA is label "can't remove." ...
    (microsoft.public.windowsupdate)