The cost of Invoke()... can it be done faster?

O

OPL

Hi guys..

I've got a function that copies one file to another location. The file it copies is currently about 36mb. I've got an event being fired after after every 32k buffer read from FileStream.Read(), containing the bytes read thus far and the total bytes to read.

When I don't invoke to update the UI status, the copy currently completes in just under 3 seconds. With a UI status invoke, it takes 23 seconds.

Essentially this is my event handler:
if (this.InvokeRequired)
{
this.Invoke(new ProgressRaiseDelegate(progEvent), e);
}

And progEvent simply involves setting a progress bars value to the current value. Is there a way this can be significantly sped up? Cheers.
 
S

Stephany Young

Calling Invoke will block you thread until 'progEvent' returns, thus causing
your delay.

Call BeginInvoke instaed which will allow your thread to continue
immediately.


Hi guys..

I've got a function that copies one file to another location. The file it
copies is currently about 36mb. I've got an event being fired after after
every 32k buffer read from FileStream.Read(), containing the bytes read thus
far and the total bytes to read.

When I don't invoke to update the UI status, the copy currently completes in
just under 3 seconds. With a UI status invoke, it takes 23 seconds.

Essentially this is my event handler:
if (this.InvokeRequired)
{
this.Invoke(new ProgressRaiseDelegate(progEvent), e);
}
And progEvent simply involves setting a progress bars value to the current
value. Is there a way this can be significantly sped up? Cheers.
 
T

Truong Hong Thi

There is 2 ways it can be improved:
- Call BeginInvoke, as Stephany pointed out
- Call it less often
 
M

marc.gravell

To expand on the "less often" option; firstly, you could simply fire
the event every <x> iterations (using a simple counter or module
operator); on the form, your event handler could simply update some
(synchronised) fields, and have a timer on the form check the fields
(again, synchronised) every (say) 500ms; using this approach, you a:
divorce UI and worker (except for the sync), and b: minimise the number
of messages on the queue (Invoke/BeginInvoke). At the end of the day,
the user isn't going to be able to read 200 updates a second... so
don't bother! For maximum performance, separate "reading the sync'd
fields" and "update the UI", e.g.

void Timer_Tick(...) {
string updatedStatus;
lock(SyncLock) {
updatedStatus = someField.ToString();
}
if(!string.IsNullOrEmpty(updatedStatus)) {
someControl.Text = updatedStatus;
}
}

void SomeWorker_StatusUpdated(...) {
lock(SyncLock) {
someField.AppendLine(newStatus);
}
}

Marc
 

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