error when invoke in thread

P

PiotrKolodziej

Hi. I have a form. This form calls thread.
Inside this thread i have while loop:

while ((bufferCount = FileStream.Read(buffer, 0, 64000)) > 0
&& !Stop)
{
store += bufferCount;
file.Write(buffer, 0, bufferCount);

// Update information on control
this.Invoke(updDeleg, store);
}

Stop variable is interlocked because i use it also in Dispose method:

protected override void Dispose(bool disposing)
{
Stop = true;


downloadThread.Join();


OpenForms.MainForm.LockDownload(false);

if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}


The problem is :
I dispose close form and this form is SOMETIMES ( mostly ) lagged. It's
never lagged when i delete this line from while loop:

// Update information on control
this.Invoke(updDeleg, store);


Here this simple invoked method:
private void update(long store)
{
// Update Progressbar here

}


Cant understand why its not working when using Invoke.
For any help i would be grateful
PK
 
P

PiotrKolodziej

I have also observed that when i right click form on the taskbar, form is
closed immidiately and everything return to it's normal state.
 
P

Peter Duniho

PiotrKolodziej said:
The problem is :
I dispose close form and this form is SOMETIMES ( mostly ) lagged. It's
never lagged when i delete this line from while loop:

// Update information on control
this.Invoke(updDeleg, store);

What do you mean by "lagged"?

The code you've posted has the potential for deadlock, which would stop
execution altogether. The secondary thread calls Invoke and the primary
thread calls Join on the secondary thread.

If the secondary thread calls Invoke at any time just before, or any time
after, the primary thread calls Join, the primary thread will be sitting
there waiting for the secondary thread to complete while the secondary
thread will be sitting there waiting for the primary thread to process the
invoked delegate.

Deadlock.

The only way to fix it is to not write code in which both threads can at the
same time be waiting on the other.

Pete
 
S

Stoitcho Goutsev \(100\)

Piotr,

Here what I believe the problem is - calling invoke on a control uses the
message loop to do the thread switching. That means the main UI thread must
run the message loop in order this to work. However when you call dispose
you join the download thread that cause the main UI thread to stop pumping
messages and if it happens just before the downloading thread to call the
Invoke method you get yourself in a deadlock situation. According to the
documentation Join keeps processing the massages that are sent, but in this
case the message that the Invoke method uses is posted, so the deadlock is
there.
 
W

Willy Denoyette [MVP]

| Hi. I have a form. This form calls thread.
| Inside this thread i have while loop:
|
| while ((bufferCount = FileStream.Read(buffer, 0, 64000)) >
0
| && !Stop)
| {
| store += bufferCount;
| file.Write(buffer, 0, bufferCount);
|
| // Update information on control
| this.Invoke(updDeleg, store);
| }
|
| Stop variable is interlocked because i use it also in Dispose method:
|
| protected override void Dispose(bool disposing)
| {
| Stop = true;
|
|
| downloadThread.Join();
|
|
| OpenForms.MainForm.LockDownload(false);
|
| if (disposing && (components != null))
| {
| components.Dispose();
| }
| base.Dispose(disposing);
| }
|
|
| The problem is :
| I dispose close form and this form is SOMETIMES ( mostly ) lagged. It's
| never lagged when i delete this line from while loop:
|
| // Update information on control
| this.Invoke(updDeleg, store);
|
|
| Here this simple invoked method:
| private void update(long store)
| {
| // Update Progressbar here
|
| }
|
|
| Cant understand why its not working when using Invoke.
| For any help i would be grateful
| PK
|
|


Invoke post's a message and a delegate to the UI thread and waits for the
underlying delegate's function to return. Whenever you call Join in the UI
thread, you block the UI thread and as such it's message pump (well not
exactly, because Join performs some limitted pumping). That means that you
prevent the background thread to make progress, and as such you keep the UI
thread from making progress too, result: deadlock.

There are several way's to solve this issue:
- use BeginInvoke instead of Invoke,
- use some synchronization primitive, like an event, in order to coordinate
distinct thread's activities.
- use the Join overload with a timeout value (say 20 msec) in an loop in
order to pump some more messages, like ....
while(t.Join(20) == false)


Willy.



Willy.
 
P

PiotrKolodziej

Invoke post's a message and a delegate to the UI thread and waits for the
underlying delegate's function to return. Whenever you call Join in the UI
thread, you block the UI thread and as such it's message pump (well not
exactly, because Join performs some limitted pumping). That means that you
prevent the background thread to make progress, and as such you keep the
UI
thread from making progress too, result: deadlock.

There are several way's to solve this issue:
- use BeginInvoke instead of Invoke,
- use some synchronization primitive, like an event, in order to
coordinate
distinct thread's activities.
- use the Join overload with a timeout value (say 20 msec) in an loop in
order to pump some more messages, like ....
while(t.Join(20) == false)


Willy.


Thank you. It was really helpful.
PK
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top