473,386 Members | 1,712 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,386 software developers and data experts.

BeginInvoke and anonymous delegate

void DisplayLines(object state)
{
for (int i = 0; i < 500; ++i)
{
int iCopy = i;
rtb.BeginInvoke((MethodInvoker)delegate
{
rtb.AppendText(iCopy + "\n");
});
}
MessageBox.Show("Done");
}

I call this function from the main thread with ThreadPool's
QueueUserWorkItem method. Since I'm accessing RichTextBox variable rtb from
the different thread than the one it was created on I have to call
BeginInvoke method.

Above code seems to work fine but I'm not sure if it's guaranteed to since
iCopy, the variable that is accessed from within the delegate, potentially
goes out of scope before delegate is invoked. Does this mean that iCopy can
be destroyed prior to delegate accessing it?
Sep 3 '06 #1
11 9384
Hello, Dean!
You wrote on Sun, 3 Sep 2006 03:25:48 +0200:

DSAbove code seems to work fine but I'm not sure if it's guaranteed to
since
DSiCopy, the variable that is accessed from within the delegate,
potentially
DSgoes out of scope before delegate is invoked. Does this mean that iCopy
can
DSbe destroyed prior to delegate accessing it?

iCopy will become a member of the hidden class
Have a look at for more details how anonymous delegates work
( http://blogs.msdn.com/oldnewthing/ar...02/686456.aspx )

--
Regards, Vadym Stetsyak.
Blog: http://vadmyst.blogspot.com
Sep 3 '06 #2
A better solution is to build the string on the background thread
(ideally using a StringBuilder instance), and then perform a *single*
BeginInvoke to the UI thread to "rtb.AppendText(sb.ToString());". This
is a: more efficient (less message posting etc), but more importantly,
b: it is simpler: you don't need to worry about the lifetime so much.
Oh, and c: it will cause less UI updates, making the UI thread more
efficient, and smoother... but the UI will update in a single jump. If
this is a problem, you could always to a .Invoke whenever for instance
i % 100 is zero (and then once at the end) - the .Invoke avoids any
question of accessing the captured variable from two threads, and you
still see a progressively growing UI...

Marc

Sep 3 '06 #3
On Sun, 3 Sep 2006 20:48:27 +0300, Vadym Stetsyak wrote:
Hello, Dean!
You wrote on Sun, 3 Sep 2006 03:25:48 +0200:

DSAbove code seems to work fine but I'm not sure if it's guaranteed to
since
DSiCopy, the variable that is accessed from within the delegate,
potentially
DSgoes out of scope before delegate is invoked. Does this mean that iCopy
can
DSbe destroyed prior to delegate accessing it?

iCopy will become a member of the hidden class
Have a look at for more details how anonymous delegates work
( http://blogs.msdn.com/oldnewthing/ar...02/686456.aspx )
Thanks.
Sep 3 '06 #4
On 3 Sep 2006 12:10:45 -0700, Marc Gravell wrote:
A better solution is to build the string on the background thread
(ideally using a StringBuilder instance), and then perform a *single*
BeginInvoke to the UI thread to "rtb.AppendText(sb.ToString());". This
is a: more efficient (less message posting etc), but more importantly,
b: it is simpler: you don't need to worry about the lifetime so much.
Oh, and c: it will cause less UI updates, making the UI thread more
efficient, and smoother... but the UI will update in a single jump. If
this is a problem, you could always to a .Invoke whenever for instance
i % 100 is zero (and then once at the end) - the .Invoke avoids any
question of accessing the captured variable from two threads, and you
still see a progressively growing UI...

Marc
I know that building the string first would be more efficient but I
couldn't do that easily because the data (from the socket) comes in a
non-predictable way. I could get one message in 100 seconds or 100 messages
in 1 second.

As far as Invoke goes I believe it would give me some efficiency penalty
because the socket thread would have to wait for the string to be displayed
before it could continue.
Sep 3 '06 #5
You don't have to worry about this. The compiler generates a class
which is used to make the call to the anonymous delegate (which has the
method that is called). This class also will have members for the class
that contains this method (a field that ends in "this") as well as a member
for the iCopy variable.

In each iteration of the loop, a new instance of this class is created,
with the iCopy member field set, before the method to call is passed to
BeginInvoke.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Dean Shimic" <ds****@gmail.comwrote in message
news:1h*****************************@40tude.net...
void DisplayLines(object state)
{
for (int i = 0; i < 500; ++i)
{
int iCopy = i;
rtb.BeginInvoke((MethodInvoker)delegate
{
rtb.AppendText(iCopy + "\n");
});
}
MessageBox.Show("Done");
}

I call this function from the main thread with ThreadPool's
QueueUserWorkItem method. Since I'm accessing RichTextBox variable rtb
from
the different thread than the one it was created on I have to call
BeginInvoke method.

Above code seems to work fine but I'm not sure if it's guaranteed to since
iCopy, the variable that is accessed from within the delegate, potentially
goes out of scope before delegate is invoked. Does this mean that iCopy
can
be destroyed prior to delegate accessing it?

Sep 3 '06 #6
Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard.caspershouse.comwrote:
You don't have to worry about this. The compiler generates a class
which is used to make the call to the anonymous delegate (which has the
method that is called). This class also will have members for the class
that contains this method (a field that ends in "this") as well as a member
for the iCopy variable.

In each iteration of the loop, a new instance of this class is created,
with the iCopy member field set, before the method to call is passed to
BeginInvoke.
Note that if you used "i" instead of "iCopy" you'd still get the same
behaviour - "i" would be captured in that case.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Sep 4 '06 #7
Good reasoning, but you didn't mention the sockets ;-p

One other approach (more suitable in the sockets case) is to batch the
updates in a container class, and simply have a timer on the UI thread that
sucks the new lines from the collection and clears it - dummied below (note
thread safety); this avoids lots of messaging in terms of .BeginInvoke /
..Invoke, and performs fewer UI updates (e.g. set the timer to 250ms or
something). In almost all cases the lock will be uncontested (so very fast -
probably faster than the .BeginInvoke step), and even when contested the
block is short-lived (we don't update the UI while holding the lock).

I've used this approach to great effect when dealing with mid-to-high volume
updates from multiple threads.

Marc

readonly StringBuilder newLines = new StringBuilder();
public void AddLinesTimer_Tick(object sender, EventArgs args) {
string toAdd;
lock(newLines) {
toAdd = newLines.ToString();
toAdd.Length = 0; // wipe
}
if(toAdd.Length 0) {
someControl.Text += toAdd;
}
}

public void SomeWorker() {
for(some loop) {
string newLine = "blah";
if(newLine.Length 0) {
lock(newLines) { // lock per iteration, not for the entire loop
newLines.AppendLine(newLine);
}
}
}
}
Sep 4 '06 #8
On Mon, 4 Sep 2006 07:09:13 +0100, Jon Skeet [C# MVP] wrote:
Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard.caspershouse.comwrote:
> You don't have to worry about this. The compiler generates a class
which is used to make the call to the anonymous delegate (which has the
method that is called). This class also will have members for the class
that contains this method (a field that ends in "this") as well as a member
for the iCopy variable.

In each iteration of the loop, a new instance of this class is created,
with the iCopy member field set, before the method to call is passed to
BeginInvoke.

Note that if you used "i" instead of "iCopy" you'd still get the same
behaviour - "i" would be captured in that case.
Actually it doesn't. That is what I was using initially but if you add a
Thread.Sleep(10); in the delegate body output will end up being something
like 0, 500, 500, 500, etc.
Sep 4 '06 #9
On Mon, 4 Sep 2006 09:02:37 +0100, Marc Gravell wrote:
Good reasoning, but you didn't mention the sockets ;-p

One other approach (more suitable in the sockets case) is to batch the
updates in a container class, and simply have a timer on the UI thread that
sucks the new lines from the collection and clears it - dummied below (note
thread safety); this avoids lots of messaging in terms of .BeginInvoke /
.Invoke, and performs fewer UI updates (e.g. set the timer to 250ms or
something). In almost all cases the lock will be uncontested (so very fast -
probably faster than the .BeginInvoke step), and even when contested the
block is short-lived (we don't update the UI while holding the lock).

I've used this approach to great effect when dealing with mid-to-high volume
updates from multiple threads.
[cut]

That's a clever way of doing it. I'll try and see how it behaves in my own
program.
Sep 4 '06 #10
Dean Shimic <ds****@gmail.comwrote:
Note that if you used "i" instead of "iCopy" you'd still get the same
behaviour - "i" would be captured in that case.

Actually it doesn't. That is what I was using initially but if you add a
Thread.Sleep(10); in the delegate body output will end up being something
like 0, 500, 500, 500, etc.
Doh - you're absolutely right. The variable would be captured, not the
value. It's this kind of thing which suggests caution when it comes to
anonymous methods :) (Alternatively, it suggests not posting before the
first coffee of the morning...)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Sep 4 '06 #11
If you get time, please let me / us know how you get on...

Marc

Sep 4 '06 #12

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

Similar topics

1
by: Grandma Wilkerson | last post by:
My question concerns the documentation for Control.BeginInvoke(). At one point is says: "Executes the specified delegate asynchronously with the specified arguments, on the thread that the...
2
by: Sandor Heese | last post by:
Question, When using BeginInvoke (on a From to marshal to the UI thread) with the EventHandler delegate I see some strange behaviour. The problem is that I call the UpdateTextBox method with a...
6
by: arkam | last post by:
Hi, I found a sample on internet : formMain.BeginInvoke(new MyClickHandler(this.OnMyClick)); I would like to do the same but in a class library where there is no forms ! Where can I find...
4
by: Jon | last post by:
Why are out parmeters included in an BeginInvoke? They seem to do nothing? TestProgam: using System; namespace TempConsole { class App { public delegate void MyDelegate( out byte b, out...
6
by: Valerie Hough | last post by:
I'm not entirely sure what the difference is between these two approaches. In order to avoid reentrant code, I was using Control.BeginInvoke in my UI to cause an asynchronous activity to be done...
9
by: john doe | last post by:
I have a question about BeginInvoke method found on the Control class. To quote the docs: "Executes the specified delegate asynchronously with the specified arguments, on the thread that the...
2
by: Flack | last post by:
Hello, If I understand BeginInvoke correctly, when it is called your delegate is run on a thread pool thread. Now, if you supplied a callback delegate, that too is called on the same thread...
10
by: kimiraikkonen | last post by:
Hi, I have a small app which sends using .NET's SmtpClient Class and sends well. But the problem is that i placed a marquee-type progress bar to have an animation and hide by default. Then i...
7
by: Ben Voigt [C++ MVP] | last post by:
As much as the CLR team assures us that it's ok to fire-and-forget Control.BeginInvoke, it seems it isn't. Maybe this is a bug. See for example: the comments in...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
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: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
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
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
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
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

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.