473,394 Members | 1,889 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

Thread and GUI update problem

To all,

I have a GUI program (use c#), and I have create a Thread for loading
some bulk data, I also arrange the GUI program like this:

1) load a form showing "Wait for loading..." etc
2) a Thread is then created to load the bulk data
3) after the thread has completed, close the "Wait for loading" form
4) show the main form for the GUI program

The problem is that if I show the "waiting" form, that form's GUI will
not work properly (no repaint event and hangs around, ie. a blank
window), the worse thing is that the Thread may not work properly too
(actually it will stop executing, waiting for locks, maybe ??)

But if I start the Thread without showing any forms; it works
perfectly ????!

What's wrong ?? (the same things happen under .Net Compact Framework)

[code snippet for the main GUI form]
public class Trial04_02 : System.Windows.Forms.Form
{
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button button1;
private System.ComponentModel.Container components = null;
private Trial04_01 mFrmSplash;
private Thread mThr_Main;
private System.Windows.Forms.ListBox listBox1;
private CommonEngine02 mCEng;

public Trial04_02()
{
InitializeComponent();
init ();
}

private void InitializeComponent() {}

protected void init ()
{
// 1st show splash form
this.mFrmSplash = new Trial04_01 ();
//this.mFrmSplash.Show ();

// 2nd create a thread to load sth...
// CommonEngine02 is a class containing the
// data loading function
this.mCEng = new CommonEngine02 (); this.mThr_Main = new Thread
(new ThreadStart (this.mCEng.threadTask));
this.mThr_Main.Start ();
this.mThr_Main.Join ();
this.mFrmSplash.Close ();

// 3rd other setup(s)
// get back the loaded data
System.Collections.ArrayList oArr
= this.mCEng.getArr_Data ();
for (int i=0; i<oArr.Count; i++)
{
this.listBox1.Items.Add (oArr[i]);
}
this.Show ();
}

static void Main ()
{
Application.Run (new Trial04_02 ());
}
}
}

[/code]
From Jason (Kusanagihk)
Nov 16 '05 #1
13 3593
Hi Jason,

It looks like your form "mFrmSplash" (main thread) waits at
"this.mThr_Main.Join()" line, so it can not be "invalidated".

I can propose:
A) "mFrmSplash.Close() && this.Show()" within
thread "mThr_Main".
or
B) run third thread that will wait ("this.mThr_Main.Join()")
and then will close the splash form and show the main window.

Regads

Marcin
To all,

I have a GUI program (use c#), and I have create a Thread for loading
some bulk data, I also arrange the GUI program like this:

1) load a form showing "Wait for loading..." etc
2) a Thread is then created to load the bulk data
3) after the thread has completed, close the "Wait for loading" form
4) show the main form for the GUI program

The problem is that if I show the "waiting" form, that form's GUI will
not work properly (no repaint event and hangs around, ie. a blank
window), the worse thing is that the Thread may not work properly too
(actually it will stop executing, waiting for locks, maybe ??)

But if I start the Thread without showing any forms; it works
perfectly ????!

What's wrong ?? (the same things happen under .Net Compact Framework)

[code snippet for the main GUI form]
public class Trial04_02 : System.Windows.Forms.Form
{
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button button1;
private System.ComponentModel.Container components = null;
private Trial04_01 mFrmSplash;
private Thread mThr_Main;
private System.Windows.Forms.ListBox listBox1;
private CommonEngine02 mCEng;

public Trial04_02()
{
InitializeComponent();
init ();
}

private void InitializeComponent() {}

protected void init ()
{
// 1st show splash form
this.mFrmSplash = new Trial04_01 ();
//this.mFrmSplash.Show ();

// 2nd create a thread to load sth...
// CommonEngine02 is a class containing the
// data loading function
this.mCEng = new CommonEngine02 (); this.mThr_Main = new Thread
(new ThreadStart (this.mCEng.threadTask));
this.mThr_Main.Start ();
this.mThr_Main.Join ();
this.mFrmSplash.Close ();

// 3rd other setup(s)
// get back the loaded data
System.Collections.ArrayList oArr
= this.mCEng.getArr_Data ();
for (int i=0; i<oArr.Count; i++)
{
this.listBox1.Items.Add (oArr[i]);
}
this.Show ();
}

static void Main ()
{
Application.Run (new Trial04_02 ());
}
}
}

[/code]
From Jason (Kusanagihk)

Nov 16 '05 #2
Jason Jacob <50******@alumni.cityu.edu.hk> wrote:
I have a GUI program (use c#), and I have create a Thread for loading
some bulk data, I also arrange the GUI program like this:

1) load a form showing "Wait for loading..." etc
2) a Thread is then created to load the bulk data
3) after the thread has completed, close the "Wait for loading" form
4) show the main form for the GUI program


There's no point in creating a new thread if you're immediately going
to call Join on it. Instead, you need to run the UI thread as normal,
and have some kind of call when the load finishes to tell the loading
screen to close.

See http://www.pobox.com/~skeet/csharp/multithreading.html for more
information.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #3
To Jon,

I've changed the code as you've said, actually there is no change in
the problem:

public Form1()
{
InitializeComponent();

oFrm2 = new Form2 ();
Thread t1 = new Thread
(new ThreadStart (oFrm2.threadTask));
t1.Start ();

loaderTask ();
oFrm2.mBool_Stop = true;
lock (this)
{
t1.Join ();
oFrm2.Close ();
}
}

The above code is the constructor code for the operation, threadTask
will change the Splash Form's Label's Text, but when got them
executed, the Splash Form's UI is not updating properly...

But then, I've tried to use oFrm2.ShowDialog () instead of oFrm2.Show
(), the result is that the Splash Form can be shown properly, but
actually it is not a Thread, since the form is waiting for you to
close it (Dialog), then it will continue the other tasks started
earlier...

From Jason (Kusanagihk)
Nov 16 '05 #4
Jason Jacob <50******@alumni.cityu.edu.hk> wrote:
I've changed the code as you've said, actually there is no change in
the problem:

public Form1()
{
InitializeComponent();

oFrm2 = new Form2 ();
Thread t1 = new Thread
(new ThreadStart (oFrm2.threadTask));
t1.Start ();

loaderTask ();
oFrm2.mBool_Stop = true;
lock (this)
{
t1.Join ();
oFrm2.Close ();
}
}

The above code is the constructor code for the operation, threadTask
will change the Splash Form's Label's Text, but when got them
executed, the Splash Form's UI is not updating properly...
The constructor is not going to finish executing until the thread has
finished though, so you aren't starting a message pump.
But then, I've tried to use oFrm2.ShowDialog () instead of oFrm2.Show
(), the result is that the Splash Form can be shown properly, but
actually it is not a Thread, since the form is waiting for you to
close it (Dialog), then it will continue the other tasks started
earlier...


In the above, you aren't even showing oFrm2 at all. You should start
the thread and then have that tell the splash screen to close when it's
finished. Using Thread.Join is *not* a good idea when called from the
UI thread.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #5
To Jon,

I've modified the code, and start the Thread outside the constructor.
Now it is works a bit "normal" to me. However the Splash Form still
can't change its GUI's properties (eg. I want to change a Label's text
showing the Time elapsed from loading etc..., it still won't update
for now)

And Join a UI Thread is not a *good* idea, what does that mean ??

the new code
Expand|Select|Wrap|Line Numbers
  1. namespace Splash_Trial.Trial02
  2. {
  3. public class Form1 : System.Windows.Forms.Form
  4. {
  5. ..........
  6.  
  7. // Constructor
  8. public Form1()
  9. {
  10. InitializeComponent();
  11.  
  12. this.Show ();
  13. }
  14.  
  15. protected void loaderTask ()
  16. {
  17. // do some bulky things such as reading lots of data
  18. ...............
  19. }
  20.  
  21. protected override void Dispose( bool disposing ){ //.... }
  22.  
  23. protected void threadTask ()
  24. {
  25. oFrm2 = new Form2 ();
  26. Thread t1 = new Thread
  27. (new ThreadStart (oFrm2.threadTask));
  28. t1.Start ();
  29.  
  30. loaderTask ();  // the bulky work
  31. oFrm2.mBool_Stop = true;
  32. t1.Join ();
  33. oFrm2.Close ();
  34. }
  35.  
  36. [STAThread]
  37. static void Main()
  38. {
  39. Form1 oFrm1 = new Form1 ();
  40. oFrm1.threadTask ();
  41. Application.Run(oFrm1);
  42. }
  43. }
  44. }
  45.  
  46.  
From Jason (Kusanagihk)
Nov 16 '05 #6
Jason Jacob <50******@alumni.cityu.edu.hk> wrote:
I've modified the code, and start the Thread outside the constructor.
Now it is works a bit "normal" to me. However the Splash Form still
can't change its GUI's properties (eg. I want to change a Label's text
showing the Time elapsed from loading etc..., it still won't update
for now)
You need to use Control.Invoke or Control.BeginInvoke to update the UI
from a non-UI thread. Did you read the article I pointed you to before?
It has an example of doing this kind of thing.
And Join a UI Thread is not a *good* idea, what does that mean ??


It means you shouldn't do it, because your app's UI won't be able to
process any events (like painting) until the other thread has finished.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #7
To Jon

I've read the "Threading in Windows Form" from your link. I have
modified the code to use Control.Invoke, but still some strange
things. If I don't add a Refresh () code, the UI won't update; if I
try to click or do anything on the splash form, the UI will not
respond (a "not responding" appears on the form's title bar.

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

using System.Threading;

namespace ThreadCookBook.Trial05
{
public class Form2 : System.Windows.Forms.Form
{
private System.Windows.Forms.Label label1;
private System.ComponentModel.Container components = null;
public delegate void invokeTask ();
public invokeTask mInvokeTask;
private bool mBool_Stop = false;

public Form2()
{
InitializeComponent();
this.mInvokeTask = new invokeTask
(this.realInvokeTask);
}

public void realInvokeTask ()
{
Random ran = new Random
((int) System.DateTime.Now.Ticks);
int iR = ran.Next (255);
int iG = ran.Next (255);
int iB = ran.Next (255);

this.label1.Text = System.DateTime.Now + "";
this.BackColor = Color.FromArgb (iR, iG, iB);
this.Refresh ();
}

protected override void Dispose( bool disposing ) { //... }
private void InitializeComponent() { //... }

public void threadTask ()
{
if (this.Visible == false)
{
this.Show ();
}
while (!this.mBool_Stop)
{
Invoke (this.mInvokeTask);
Thread.Sleep (2000);
}
}

public void setStop (bool flag)
{
this.mBool_Stop = flag;
}
}
}
From Jason (Kusanagihk)
Nov 16 '05 #8
Jason Jacob <50******@alumni.cityu.edu.hk> wrote:
I've read the "Threading in Windows Form" from your link. I have
modified the code to use Control.Invoke, but still some strange
things. If I don't add a Refresh () code, the UI won't update; if I
try to click or do anything on the splash form, the UI will not
respond (a "not responding" appears on the form's title bar.


Well you're now not showing the code which creates the new thread.
Please post a *complete* program which demonstrates the problem, and
we'll be able to get somewhere.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #9
To Jon

The Main Form's code

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Threading;

namespace ThreadCookBook.Trial05
{
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.ListBox listBox1;
private System.Windows.Forms.Button button1;
private System.ComponentModel.Container components = null;
private Thread mThr_ThreadTask;
// a class to load some bulky data
private CommonEngine02 mCEng02;
// the Splash Form
private Form2 mFrm02;

public Form1()
{
InitializeComponent();
init ();
}

protected override void Dispose( bool disposing ) { //... }
private void InitializeComponent() { //... }

protected void init ()
{
this.mCEng02 = new CommonEngine02 ();
}

protected void loaderTask ()
{
this.threadTask ();
// blocking, load the bulky data ...
this.mCEng02.threadTask ();
// try to stop the loop in the Splash Form
lock (this)
{
this.mFrm02.setStop (true);
this.mFrm02.Close ();
}
// get back the bulky data and add them to a listBox
ArrayList oArr = this.mCEng02.getArr_Data ();
for (int i=0; i<oArr.Count; i++)
{
this.listBox1.Items.Add (oArr[i]);
}
}

public void threadTask ()
{
this.mFrm02 = new Form2 ();
this.mThr_ThreadTask = new Thread
(new ThreadStart (this.mFrm02.threadTask));
this.mThr_ThreadTask.Start ();
}

static void Main ()
{
// maybe here's where the problem is...
Form1 oFrm01 = new Form1 ();
oFrm01.loaderTask ();
Application.Run (oFrm01);
}
}
}

From Jason (Kusanagihk)
Nov 16 '05 #10
Jason Jacob <50******@alumni.cityu.edu.hk> wrote:
The Main Form's code


That's *still* not a complete example.

However, the problem certainly does seem to be that you're doing all
the actual work before calling Application.Run, so you're not starting
the message pump on the thread until rather late.

Also, although you're *creating* an instance of Form2, you're never
showing it, as far as I can see.

By the way, I'd strongly recommend using MS's naming conventions:
http://tinyurl.com/2cun

You might also want to think about giving your classes more meaningful
names :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #11
To Jon

Um... I think I may need a simple guideline to implement Splash
Screen(s). Since my prior trials are on a wrong track, I think it is
difficult to code the right things out........

According to your suggestion, it seems that I may need another program
(maybe a console app) to start 2 threads (1 is for the main form --
loading bulky things etc, the other thread is for the Splash Screen),
then somehow the extra app will control when to kill the Splash Form
and show the main form out.
(Is that correct ???)

Full of question marks.......

From Jason (Kusanagihk)
Nov 16 '05 #12
Jason Jacob <50******@alumni.cityu.edu.hk> wrote:
Um... I think I may need a simple guideline to implement Splash
Screen(s). Since my prior trials are on a wrong track, I think it is
difficult to code the right things out........

According to your suggestion, it seems that I may need another program
(maybe a console app) to start 2 threads (1 is for the main form --
loading bulky things etc, the other thread is for the Splash Screen),
then somehow the extra app will control when to kill the Splash Form
and show the main form out.
(Is that correct ???)


No, you don't need another program at all. You need to have one thread
which is just running the UI, via Application.Run. It shows the splash
screen, and starts another thread. When the other thread has finished
what it needs to do, it signals that to the UI thread, which puts up
the real UI instead.

One tricky thing here is that you may need to use the version of
Application.Run which *doesn't* take a Form, as otherwise when that
Form is closed, you'll end up losing the message pump.

Alternatively, you could call Application.Run on the splash screen, and
then Application.Run on the main UI.

Alternatively (again) you could create the main UI form and have it as
non-visible, create the splash screen as visible, and call
Application.Run on the main UI form.

Here's a version which uses the middle idea:

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Threading;

using Timer = System.Windows.Forms.Timer;

delegate void LoadFinishedHandler();

class Test
{

static void Main()
{
Loader loader = new Loader();
SplashScreen splash = new SplashScreen(loader);
Application.Run (splash);
Application.Run (new MainForm());
}
}

class SplashScreen : Form
{
ProgressBar progress;
Timer timer;

public SplashScreen (Loader loader)
{
loader.LoadFinished += new LoadFinishedHandler(LoadFinished);
ControlBox = false;
Size = new Size(200, 80);
StartPosition = FormStartPosition.CenterScreen;

Label lbl = new Label();
lbl.Text = "Please wait";
lbl.Size = new Size (100, 20);
lbl.Location = new Point (10, 20);
Controls.Add(lbl);

progress = new ProgressBar();
progress.Minimum = 1;
progress.Maximum = 5;
progress.Step = 1;
progress.Value = 1;
progress.Size = new Size (160, 20);
progress.Location = new Point (10, 50);
Controls.Add(progress);

timer = new Timer();
timer.Interval = 500;
timer.Tick += new EventHandler (TimerTick);
timer.Enabled = true;

loader.Start();
}

void TimerTick(object sender, EventArgs e)
{
if (progress.Value == progress.Maximum)
{
progress.Value = progress.Minimum;
}
else
{
progress.PerformStep();
}
}

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
timer.Dispose();
}

void LoadFinished()
{
if (InvokeRequired)
{
Invoke(new LoadFinishedHandler(LoadFinished));
return;
}
Close();
}
}

class MainForm : Form
{
public MainForm()
{
Size = new Size(300, 300);
StartPosition = FormStartPosition.CenterScreen;

Label lbl = new Label();
lbl.Text = "Main UI goes here";
lbl.Size = new Size (100, 20);
lbl.Location = new Point (10, 20);
Controls.Add(lbl);
}
}

class Loader
{
object stateLock = new object();
LoadFinishedHandler loadFinishedDelegate;

public event LoadFinishedHandler LoadFinished
{
add
{
lock (stateLock)
{
loadFinishedDelegate += value;
}
}
remove
{
lock (stateLock)
{
loadFinishedDelegate -= value;
}
}
}

protected virtual void OnLoadFinished()
{
LoadFinishedHandler handler;
lock (stateLock)
{
handler = loadFinishedDelegate;
}
if (handler != null)
{
handler();
}
}

public void Start()
{
new Thread (new ThreadStart(Load)).Start();
}

void Load()
{
// Obviously you'd do real stuff here
Thread.Sleep(5000);
OnLoadFinished();
}
}

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #13
To Jon

Thanks for your advice, I am now your code example to implement the
splash screen and it work fine!

This problem really has taken me too much time.......

Thanks!

From Jason (Kusanagihk)
Nov 16 '05 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

44
by: Charles Law | last post by:
Hi guys. I'm back on the threading gig again. It's the age-old question about waiting for something to happen without wasting time doing it. Take two threads: the main thread and a worker...
12
by: serge calderara | last post by:
Dear all, I have a function that I need to run in a thread due to the fact that it can takes long time to execute according to the amount of data to collect. This function is also populating a...
2
by: BG | last post by:
We're having trouble writing the code to update a UI control (label.Text) from a secondary thread. We're using C# with Windows Forms. We have a main form named MainForm, a splash screen form...
2
by: Don Tucker | last post by:
Hello, I am using Visual Studio 2005 .Net, coding in C#. I am working through the threading walkthrough: ...
9
by: Jervin Justin | last post by:
Hi, I've been having this problem for some time with Web Forms: I have a web app that sends data to a service when the user presses a button. Based on the data, the server will send several...
4
by: Charles Law | last post by:
Hi guys. I have two threads: a main thread and a background thread. Lots of stuff happens in the background thread that means I have to update several (lots) of controls on a form. It is...
14
by: joey.powell | last post by:
I am using VS2005 for a windows forms application. I need to be able to use a worker thread function to offload some processing from the UI thread. The worker thread will need access to a...
8
by: =?Utf-8?B?R3JlZyBMYXJzZW4=?= | last post by:
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...
20
by: cty0000 | last post by:
I have some question.. This is my first time to use thread.. Following code does not have error but two warring The warring is Warning 2 'System.Threading.Thread.Suspend()' is obsolete:...
5
by: P.J.M. Beker | last post by:
Hi there, I'm currently writing a program in which I use the FileMonitor to monitor a folder in which I store downloaded images. I know that I can't add much coding in the filemonitor's event in...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.