473,595 Members | 2,474 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Anonymous Methods As ThreadStarts

I read an article that had a really elegant solution to pass parameters
to a thread by using an anonymous method as your ThreadStart. It
seemed pretty slick and even worked when I tried it. However, with
some more playing around, I got some really strange results. Using the
code below, sometimes my output is 2 and 3. Sometimes, it's 3 and 3.
However, it's never been 1 and 2 which is what I would expect. Can
anybody set me straight on why I'm getting the unexpected results? My
suspicion is that somehow my integer is getting passed by reference
rather than value, but I'd like someone else to corroborate that before
I go on believing it. (Note: I know about ParameterizedTh readStart.
I'm just trying to use this example to understand anonymous methods a
little better.)

namespace AnonymousConfus ion
{
class Program
{
static void Main(string[] args)
{
int i = 1;

ThreadStart ts1 = delegate { WorkThread(i); };
Thread t1 = new Thread(ts1);
// i should be 1 when i'm starting my thread, right?
t1.Start();

i++;

ThreadStart ts2 = delegate { WorkThread(i); };
Thread t2 = new Thread(ts2);
// i should 2 when i'm starting my thread, right?
t2.Start();

i++;

t1.Join();
t2.Join();

// why am i getting 2 and 3 or sometimes 3 and 3 for
output?
Console.WriteLi ne("Done");
Console.ReadLin e();
}

static void WorkThread(int i)
{
Console.WriteLi ne(i.ToString() );
}
}
}

Mar 10 '06 #1
7 2228
This has nothing to do with Anonymous methods, other than the fact that you
used an anonymous method to create the threads.

The nature of threads is that they run independently of each other and of
the parent thread. Therefore, the time it takes for each thread to process
is in no way related to the order in which they are created.

--
HTH,

Kevin Spencer
Microsoft MVP
..Net Developer

Presuming that God is "only an idea" -
Ideas exist.
Therefore, God exists.

<d2*****@yahoo. com> wrote in message
news:11******** **************@ i39g2000cwa.goo glegroups.com.. .
I read an article that had a really elegant solution to pass parameters
to a thread by using an anonymous method as your ThreadStart. It
seemed pretty slick and even worked when I tried it. However, with
some more playing around, I got some really strange results. Using the
code below, sometimes my output is 2 and 3. Sometimes, it's 3 and 3.
However, it's never been 1 and 2 which is what I would expect. Can
anybody set me straight on why I'm getting the unexpected results? My
suspicion is that somehow my integer is getting passed by reference
rather than value, but I'd like someone else to corroborate that before
I go on believing it. (Note: I know about ParameterizedTh readStart.
I'm just trying to use this example to understand anonymous methods a
little better.)

namespace AnonymousConfus ion
{
class Program
{
static void Main(string[] args)
{
int i = 1;

ThreadStart ts1 = delegate { WorkThread(i); };
Thread t1 = new Thread(ts1);
// i should be 1 when i'm starting my thread, right?
t1.Start();

i++;

ThreadStart ts2 = delegate { WorkThread(i); };
Thread t2 = new Thread(ts2);
// i should 2 when i'm starting my thread, right?
t2.Start();

i++;

t1.Join();
t2.Join();

// why am i getting 2 and 3 or sometimes 3 and 3 for
output?
Console.WriteLi ne("Done");
Console.ReadLin e();
}

static void WorkThread(int i)
{
Console.WriteLi ne(i.ToString() );
}
}
}

Mar 10 '06 #2
This makes perfect sense; the "i" in the anonymous delegate (I'm not on
about WorkThread here, just the bit in the braces) is the same i - and it
all depends on timing:

[thread 1] i=1
[thread 1] go to start a thread
[thread 1] increment i (now = 2)
[thread 2] catches up, call WorkThread with i, currently 2
[thread 1] go to start a thread
[thread 1] increment i (now = 3)
[thread 3] catches up, call WorkThread with i, currently 3

or

[thread 1] i=1
[thread 1] go to start a thread
[thread 1] increment i (now = 2)
[thread 1] go to start a thread
[thread 1] increment i (now = 3)
[thread 2] catches up, call WorkThread with i, currently 3
[thread 3] catches up, call WorkThread with i, currently 3

In a way, you have been lucky; this type of usage could also lead to
completely phantom reads of i, particularly if i is of a larger data-type
(long etc); for this (latter) reason you should *always* sync access to
variables when using multiple threads.

But the main behaviour makes perfect sense

Marc

<d2*****@yahoo. com> wrote in message
news:11******** **************@ i39g2000cwa.goo glegroups.com.. .
I read an article that had a really elegant solution to pass parameters
to a thread by using an anonymous method as your ThreadStart. It
seemed pretty slick and even worked when I tried it. However, with
some more playing around, I got some really strange results. Using the
code below, sometimes my output is 2 and 3. Sometimes, it's 3 and 3.
However, it's never been 1 and 2 which is what I would expect. Can
anybody set me straight on why I'm getting the unexpected results? My
suspicion is that somehow my integer is getting passed by reference
rather than value, but I'd like someone else to corroborate that before
I go on believing it. (Note: I know about ParameterizedTh readStart.
I'm just trying to use this example to understand anonymous methods a
little better.)

namespace AnonymousConfus ion
{
class Program
{
static void Main(string[] args)
{
int i = 1;

ThreadStart ts1 = delegate { WorkThread(i); };
Thread t1 = new Thread(ts1);
// i should be 1 when i'm starting my thread, right?
t1.Start();

i++;

ThreadStart ts2 = delegate { WorkThread(i); };
Thread t2 = new Thread(ts2);
// i should 2 when i'm starting my thread, right?
t2.Start();

i++;

t1.Join();
t2.Join();

// why am i getting 2 and 3 or sometimes 3 and 3 for
output?
Console.WriteLi ne("Done");
Console.ReadLin e();
}

static void WorkThread(int i)
{
Console.WriteLi ne(i.ToString() );
}
}
}

Mar 10 '06 #3
> I read an article that had a really elegant solution to pass
parameters to a thread by using an anonymous method as your
ThreadStart. It seemed pretty slick and even worked when I tried it.
However, with some more playing around, I got some really strange
results. Using the code below, sometimes my output is 2 and 3.
Sometimes, it's 3 and 3. However, it's never been 1 and 2 which is


If you take a look using Reflector or some other disassembly tool you'll
notice that a method that declares an anonymous method and has local variables
that is used in that method will have some "magic" code in it. Basically
what happens is that a class to hold the method is defined, and the local
variables in your outer method is stored in that class. When the method starts,
an object is constructed from that class and used internally. As such, your
thread(s) and outer method shares the same variables with each other. This
means that you get all the features of sharing variables easily and all the
headache when doing so with threads.

Let me show you an actual example:

public void Test()
{
String s = String.Empty;
System.Threadin g.ThreadStart ts = delegate
{
s = "Set in delegate";
};
ts();
System.Diagnost ics.Debug.Write Line(s);
}

The decompiled version of this looks like this:

public void Test()
{
MainForm.<>c__D isplayClass1 class1 = new MainForm.<>c__D isplayClass1();
class1.s = string.Empty;
ThreadStart start1 = new ThreadStart(cla ss1.<Test>b__0) ;
start1();
Debug.WriteLine (class1.s);
}

and then:

[CompilerGenerat ed]
private sealed class <>c__DisplayCla ss1
{
// Methods
public <>c__DisplayCla ss1() { }
public void <Test>b__0()
{
this.s = "Set in delegate";
}

// Fields
public string s;
}

So, as Kevin noted, the threads all work on the same variable and might not
even get scheduled some time before you increment the variable and start
the next thread, and that's why you get those results.

--
Lasse Vågsæther Karlsen
http://usinglvkblog.blogspot.com/
mailto:la***@vk arlsen.no
PGP KeyID: 0x2A42A1C2
Mar 10 '06 #4
d2*****@yahoo.c om wrote:
I read an article that had a really elegant solution to pass parameters
to a thread by using an anonymous method as your ThreadStart. It
seemed pretty slick and even worked when I tried it. However, with
some more playing around, I got some really strange results. Using the
code below, sometimes my output is 2 and 3. Sometimes, it's 3 and 3.
However, it's never been 1 and 2 which is what I would expect. Can
anybody set me straight on why I'm getting the unexpected results? My
suspicion is that somehow my integer is getting passed by reference
rather than value, but I'd like someone else to corroborate that before
I go on believing it.


It's not that it's being "passed" so much as that it's being shared
between the delegates. It's a captured variable - not really a local
variable any more.

See http://www.pobox.com/~skeet/csharp/c...delegates.html for more
information and a really scary example...

Jon

Mar 10 '06 #5

<d2*****@yahoo. com> wrote in message
news:11******** **************@ i39g2000cwa.goo glegroups.com.. .
|I read an article that had a really elegant solution to pass parameters
| to a thread by using an anonymous method as your ThreadStart. It
| seemed pretty slick and even worked when I tried it. However, with
| some more playing around, I got some really strange results. Using the
| code below, sometimes my output is 2 and 3. Sometimes, it's 3 and 3.
| However, it's never been 1 and 2 which is what I would expect. Can
| anybody set me straight on why I'm getting the unexpected results? My
| suspicion is that somehow my integer is getting passed by reference
| rather than value, but I'd like someone else to corroborate that before
| I go on believing it. (Note: I know about ParameterizedTh readStart.
| I'm just trying to use this example to understand anonymous methods a
| little better.)
|
| namespace AnonymousConfus ion
| {
| class Program
| {
| static void Main(string[] args)
| {
| int i = 1;
|
| ThreadStart ts1 = delegate { WorkThread(i); };
| Thread t1 = new Thread(ts1);
| // i should be 1 when i'm starting my thread, right?
| t1.Start();
|
| i++;
|
| ThreadStart ts2 = delegate { WorkThread(i); };
| Thread t2 = new Thread(ts2);
| // i should 2 when i'm starting my thread, right?
| t2.Start();
|
| i++;
|
| t1.Join();
| t2.Join();
|
| // why am i getting 2 and 3 or sometimes 3 and 3 for
| output?
| Console.WriteLi ne("Done");
| Console.ReadLin e();
| }
|
| static void WorkThread(int i)
| {
| Console.WriteLi ne(i.ToString() );
| }
| }
| }
|

Before your thread gets actually a chance to run and pick up the value of i,
your main thread will have incremented the value once maybe twice.

Willy.

Mar 10 '06 #6
To get expected results, you could pass i instead of using local var capture.

Note that t2 could still complete before t1, but they should still have the expected i.

private void button3_Click(o bject sender, EventArgs e)

{

int i = 1;

Thread t1 = new Thread(WorkThre ad);

t1.Name = "t1";

t1.Start(i);

i++;

Thread t2 = new Thread(WorkThre ad);

t2.Name = "t2";

t2.Start(i);

i++;

t1.Join();

t2.Join();

}

static void WorkThread(obje ct i)

{

Console.WriteLi ne("Thread:{0} Value:{1}", Thread.CurrentT hread.Name, (int)i);

}
--
William Stacey [MVP]

Mar 10 '06 #7
Thanks. I got what I was looking for.

Mar 10 '06 #8

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

Similar topics

0
1645
by: Cordell Lawrence | last post by:
Okay guys, We are wondering if this is a bug in Framework 2.0.40607 and looking for some clarification on the issue. Take a look at the folowing code. public delegate bool BoundryTest(int myVal);
9
1623
by: John Smith | last post by:
I really can not appreciate why Microsoft has introduced Anonymous methods. It promotes quick and dirty style of programming and as I can see it offers no advantages over normal methods. I have spent years reviewing source code and asking people not to write anonymous code (supported by some non-MS high level languages) and it has made it's way to C# also!
7
1216
by: Alexandre | last post by:
cross post: Hi can someone justify the use of these anonymous methods in C# 2.0 & 3.0 ? I simply do not see a use for them. can you show me an instance where thay can be useful ?? best regards, Alexandre Brisebois
7
3784
by: Bill Woodruff | last post by:
I've found it's no problem to insert instances of named delegates as values into a generic dictionary of the form : private Dictionary<KeyType, DelegatemyDictionary = new Dictionary<KeyType, Delegate); using the standard .Add method of the Dictionary, passing in the name of the delegate instance for the value. private void myMethodBody()
22
1507
by: PJ6 | last post by:
I just learned about anonymous methods and was taken aback to discover that they are only available in C#. What, is there still a stigma against VB.Net, that maybe somehow this is a language that doesn't deserve to be as powerful as others? I hate C#. Anyway... what gives? What's the reasoning behind *that* decision? Oh I don't expect anyone to have a real answer for me. Who knows what they were thinking. I'm just ranting. I'll go sulk...
4
2382
by: Frankie | last post by:
I have just gotten up to speed on what anonymous methods are (syntax, capabilities, etc), and how they can be used with /called via delegates. What I am wondering is... 1. Are they only/mostly syntactic sugar (important as that can be)? 2. Are anonymous methods *required* anywhere? That is, are anonymous methods the only way to accomplish certain tasks in ..NET programming?
2
1838
by: Tony | last post by:
Hello! Here I have some text from a book I read. It says: "An interesting point to note concerning anonymous methods is that they are effectively local to the code block that contains them, and they have access to local variables in this scope. If you use such a variable it becomes an outer variable. Outer variables are not disposed of when they go out of scope like other local variables are; instead, they live on until the anonymous...
0
1415
by: Peter Duniho | last post by:
On Mon, 01 Sep 2008 16:14:10 -0700, Blip <blip@krumpli.comwrote: Briefly, an anonymous method is exactly that: a method without a name. When you use the "delegate" keyword to declare an anonymous method, all you're doing is writing a method the same as you would anywhere else, except that it doesn't have a name, and so you have to use it right away rather than being able to refer to it elsewhere. (And I mean that only in the static,...
4
2737
by: Peter | last post by:
Hi I've been delving into "delegates" and "anonymous methods", and now I've come across the term "closure". Some information I've found says that C# does not have closures, other information says that C# does have closures. My problem is I can't quite grasp what "closures" are. The examples I have seen seem to be "anonymous methods". What is the subtle difference
0
7955
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8261
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8379
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8019
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8251
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 protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
5839
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5418
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
3873
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
1490
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.