I have been playing around with asynchronous programming lately and it
bothers me that the last parameter to the begin invoke pattern doesn't
have a name that everyone agrees on. The begin invoke pattern is the
asynchronous calling pattern were the BeginXxxx(), such as
Stream.BeginRead(), takes a set of parameters, a callback method, and
some, well, thing, at the end that is carried along with the asynchronous
operation that eventually finds it way into the IAsyncResult. The
problem is what do we call that thing? In an informal survey of the methods in
the BCL that implement this pattern I have found a wide variation. Here is a
partial list in somewhat order of popularity,
object
stateObject
state
asyncState
extraData
data
There seems to be little agreement about what to call it. We could pick the
most prevalent but the name
object occurs the most often because every
delegate gets a BeginInvoke() method created for it and in this
automatically generated code the parameter is called object. We can't standardize on object because it is a reserved word in several languages so either it would be impossible to
specify or awkward (i.e. @object in C#). What I would like is a
name that we can all use and we can all agree on.
To name the thing, we first must understand why it it is there at all. It
exists to hold some state on behalf of the caller. Having the state object makes
programming against the begin invoke pattern easier in languages that
do not have anonymous methods that capture local variables. Consider the
following program (which intentionally ignores errors because it is only an
example),
conststring uriFormat =
"http://messenger.services.live.com/users/{0}@apps.messenger.live.com/presence";
conststring responsePattern =
@"""statusText""\s*:\s*""(?<status>\w+).*""displayName""\s*:\s*""(?<name>\w+)""";
staticvoid Main(string[] args) {
var uri = string.Format(uriFormat, args[0]);
var request = WebRequest.Create(uri);
var result = request.BeginGetResponse(PresenceCallback, request);
// Other interesting work....
result.AsyncWaitHandle.WaitOne();
}
privatestaticvoid PresenceCallback(IAsyncResult result) {
var request = result.AsyncState as WebRequest;
var response = request.EndGetResponse(result);
var s = new StreamReader(response.GetResponseStream()).ReadToEnd();
var search = new Regex(responsePattern);
var match = search.Match(s);
if (match.Success)
Console.WriteLine("{0} is {1}",
match.Groups["name"].Captures[0].Value,
match.Groups["status"].Captures[0].Value);
else
Console.WriteLine("Unexpected response");
}
This will get the online status of a Windows Live Messanger account given the
live ID account number. For example, passing 1afa695addc07e5 as an argument to
the above will tell whether or not I am online. In this case I am using last
parameter of the BeginGetResponse() method to pass the request
itself. This then is cast back to WebRequest in the
PresenceCallback() method so I can call EndGetResponse() to
retrieve the actual response. As far at the BeginGetResponse() call
is concerned, this value is opaque. It ignores it completely and just supplies
it blindly in the IAsyncResult. It makes no assumptions about the
data at all, it is just something the caller just wants carried around. If I was using
anonymous delegates in C# this would look a lot better as,
staticvoid Main(string[] args) {
var uri = string.Format(uriFormat, args[0]);
var request = WebRequest.Create(uri);
request.BeginGetResponse(result => {
var response = request.EndGetResponse(result);
var s = new StreamReader(response.GetResponseStream()).ReadToEnd();
var search = new Regex(responsePattern);
var match = search.Match(s);
if (match.Success)
Console.WriteLine("{0} is {1}",
match.Groups["name"].Captures[0].Value,
match.Groups["status"].Captures[0].Value);
else
Console.WriteLine("Unexpected response");
}
}, null);
// Other interesting work....
result.AsyncWaitHandle.WaitOne();
}
Here the request local variable request is captured
automatically by the C# compiler and placed into a compiler generated class as a
field. The compiler generated class also contains the code I supplied in the
lambda as an instance method. When I refer to response in the lambda the
reference is automatically translated into a field lookup in the generated
class. Since request is already accessible in the lambda I don't
need the last parameter to carry anything useful so I pass null.
Anonymous methods makes using callbacks much easier but since not all
languages support anonymous methods or lambdas the BCL standardized on a method
pattern for begin invoke that can easily be used by those languages. If the calling pattern did not have a caller state
object then the work performed automatically by the C# compiler would have to be
repeated manually by the programmer in these, then, second class languages. The
.NET team did not want such languages to be second class citizen (especially since neither C# nor VB.NET supported anonymous methods initially)
so they required the presence of the caller state object parameter.
Now we know why it is there, what to do we call it? I like state
because the parameter represents state the caller want's to preserve. I don't
like object because it is a common reserved word. I don't like
stateObject because a symbol's type should not be repeated in the
name, we already know it is an object by its type.
asyncState is acceptable, especially since that is the name it is given
by IAsyncResult, but it is a bit redundant, we already know, by
context, it is asynchronous state. Plus we should avoid abbreviation, like "async",
in symbol names (though it is very common, and asynchronous is very very long,
so not that bad). data seems fine to me, it is a synonym to state,
but it is overused. extraData I cannot, for the life of me, figure
out. Extra for whom? Extra as opposed to what? Unfortunately, this is the name
given to the parameter by IHttpAsyncHandler (see, I told you "async"
was common). Its name tells me nothing about what I should do with it. It
is very unclear that this value should be mapped to AsyncState in IAsyncResult.
I propose we call it state, with an acceptable variation of
asyncState.
Now, if changing a parameter name was not a breaking change...
The IM presence service returns JSON which I parse using a fancy looking
Regex instance. I recommend that production code use
DataContractJsonSerializer() instead.
I like asyncState, if only for the reason that IAsyncResult has the AsyncState property -- so the final resting spot for the value is (slightly) more clear.
I don't like 'state' doesn't tell you whose state it is, is it something that belongs to the callback that I shouldn't fiddle with?
I wouldn't call it state either, as often as not I use it to pass a reference to an object that is not purely a state object.
I would call it 'userData'.
Marc
06/17/2008 6:10 PM
I didn't recommend userData or callerState or callerData or other probably more descriptive names because they are not currently in use. I wanted to recommend one that is currently used in the BCL.
I usually use context, or much more rarely userContext.
07/15/2008 6:27 AM
I agree Chuck "userData or callerState or callerData" are good names. But if you want to limit the possible names to the BCL list, then, the "less worse" is "data". "extraData" doesn't say more than "data" (and if there's "extra" data, one will look around to find where are the "non extra" data...). So "data" is a good choice. All names with "state" are too restrictive, data is more generic. And names using "object" are colliding with some language type name as you noted it. Go for "data" so...
If you're excluding non-BCL names, I think asyncState makes the most sense (matching the propery name). On the other hand, data or asyncData is the best non-BCL name.
We've used the term "Cargo" for that kind of thing. "I'm just carrying this for someone else, I don't know/care what it is. I'll let them assume any legal responsibilities for what it is and how its used".
Starsky
08/03/2008 4:57 AM
I agree; "state" is the best name. Shame it wasn't used throughout the framework. It matches the IAsyncResult.AsyncState property name just fine. Prefixing with "async" does nothing for readability or understandability.
More like: if only changing the name of IAsyncResult weren't a breaking change, maybe more people would do async programming!
Pete
11/19/2008 2:11 AM
I always use async calls for I/O (especially sockets) and I tend to have a context object which gets passed through that parameter. It's not always a state so I would vote against anything that says "state" personally. I vote for context as a name because it's a context within which the async calls are operating.
I also like Starsky's "cargo" though - it describes what it is very well.
BeginInvoke's last parameter: What's in a name?
I have been playing around with asynchronous programming lately and it bothers me that the last parameter to the begin invoke pattern doesn't have a name that everyone agrees on. The begin invoke pattern is the asynchronous calling pattern were the
BeginXxxx(), such asStream.BeginRead(), takes a set of parameters, a callback method, and some, well, thing, at the end that is carried along with the asynchronous operation that eventually finds it way into theIAsyncResult. The problem is what do we call that thing? In an informal survey of the methods in the BCL that implement this pattern I have found a wide variation. Here is a partial list in somewhat order of popularity,There seems to be little agreement about what to call it. We could pick the most prevalent but the name
objectoccurs the most often because every delegate gets aBeginInvoke()method created for it and in this automatically generated code the parameter is calledobject. We can't standardize onobjectbecause it is a reserved word in several languages so either it would be impossible to specify or awkward (i.e.@objectin C#). What I would like is a name that we can all use and we can all agree on.To name the thing, we first must understand why it it is there at all. It exists to hold some state on behalf of the caller. Having the state object makes programming against the begin invoke pattern easier in languages that do not have anonymous methods that capture local variables. Consider the following program (which intentionally ignores errors because it is only an example),
This will get the online status of a Windows Live Messanger account given the live ID account number. For example, passing 1afa695addc07e5 as an argument to the above will tell whether or not I am online. In this case I am using last parameter of the
BeginGetResponse()method to pass the request itself. This then is cast back toWebRequestin thePresenceCallback()method so I can callEndGetResponse()to retrieve the actual response. As far at theBeginGetResponse()call is concerned, this value is opaque. It ignores it completely and just supplies it blindly in theIAsyncResult. It makes no assumptions about the data at all, it is just something the caller just wants carried around. If I was using anonymous delegates in C# this would look a lot better as,Here the request local variable
requestis captured automatically by the C# compiler and placed into a compiler generated class as a field. The compiler generated class also contains the code I supplied in the lambda as an instance method. When I refer to response in the lambda the reference is automatically translated into a field lookup in the generated class. Sincerequestis already accessible in the lambda I don't need the last parameter to carry anything useful so I passnull.Anonymous methods makes using callbacks much easier but since not all languages support anonymous methods or lambdas the BCL standardized on a method pattern for begin invoke that can easily be used by those languages. If the calling pattern did not have a caller state object then the work performed automatically by the C# compiler would have to be repeated manually by the programmer in these, then, second class languages. The .NET team did not want such languages to be second class citizen (especially since neither C# nor VB.NET supported anonymous methods initially) so they required the presence of the caller state object parameter.
Now we know why it is there, what to do we call it? I like
statebecause the parameter represents state the caller want's to preserve. I don't likeobjectbecause it is a common reserved word. I don't likestateObjectbecause a symbol's type should not be repeated in the name, we already know it is anobjectby its type.asyncStateis acceptable, especially since that is the name it is given byIAsyncResult, but it is a bit redundant, we already know, by context, it is asynchronous state. Plus we should avoid abbreviation, like "async", in symbol names (though it is very common, and asynchronous is very very long, so not that bad).dataseems fine to me, it is a synonym to state, but it is overused.extraDataI cannot, for the life of me, figure out. Extra for whom? Extra as opposed to what? Unfortunately, this is the name given to the parameter byIHttpAsyncHandler(see, I told you "async" was common). Its name tells me nothing about what I should do with it. It is very unclear that this value should be mapped toAsyncStateinIAsyncResult.I propose we call it
state, with an acceptable variation ofasyncState.Now, if changing a parameter name was not a breaking change...
Trivia:
Regexinstance. I recommend that production code useDataContractJsonSerializer()instead.1:21 PM | Comments [13] | #Programming
06/16/2008 6:11 PM
I like asyncState, if only for the reason that IAsyncResult has the AsyncState property -- so the final resting spot for the value is (slightly) more clear.But, I could live with state as well. :)
Aaron | http://www.wiredprairie.us | coderAT NOSPAMwiredprairie dot us
06/17/2008 6:06 AM
I don't like 'state' doesn't tell you whose state it is, is it something that belongs to the callback that I shouldn't fiddle with?I wouldn't call it state either, as often as not I use it to pass a reference to an object that is not purely a state object.
I would call it 'userData'.
Marc
06/17/2008 6:10 PM
I didn't recommend userData or callerState or callerData or other probably more descriptive names because they are not currently in use. I wanted to recommend one that is currently used in the BCL.Chuck Jazdzewski | www.removingalldoubt.com | chuckjAT NOSPAMmicrosoft dot com
07/14/2008 6:41 AM
I usually use context, or much more rarely userContext.07/15/2008 6:27 AM
I agree Chuck "userData or callerState or callerData" are good names. But if you want to limit the possible names to the BCL list, then, the "less worse" is "data"."extraData" doesn't say more than "data" (and if there's "extra" data, one will look around to find where are the "non extra" data...). So "data" is a good choice.
All names with "state" are too restrictive, data is more generic. And names using "object" are colliding with some language type name as you noted it.
Go for "data" so...
olivier | http://www.e-naxos.com/blog | odahanAT NOSPAMgmail dot com
07/15/2008 7:45 AM
asyncState seems fairly succinct to me. : )Scott | mailto:cmdrbeavis at gmail otDay omKay | cmdrbeavis at gmail otDay omKay
07/15/2008 11:09 AM
If you're excluding non-BCL names, I think asyncState makes the most sense (matching the propery name). On the other hand, data or asyncData is the best non-BCL name.Joshua Garvin | mailto:jkaldonAT NOSPAMgmail dot com | jkaldonAT NOSPAMgmail dot com
07/17/2008 12:44 AM
I would use AsyncData or ExtraData.Much more descriptive on what it really is.
Aralmo | mailto:aralmoAT NOSPAMgmail dot com | aralmoAT NOSPAMgmail dot com
07/18/2008 12:31 PM
data makes more sense than state (what you pass to that method is not always a state or related to that)BUT
I have absolutely no problem with state as long as I know what it does [which I do, thanks to msdn :) ]
Waheed | mailto:waheedahmedbAT NOSPAMgmail dot com | waheedahmedbAT NOSPAMgmail dot com
07/23/2008 1:28 AM
Making a fuzz about the names of variables is right up my alley. :)My vote is for state, but in a perfect world everyone would move to C# and we could loose the 'null' at the end to get:
request.BeginGetResponse(result => { ProcessResponse(request.EndGetResponse(result)); });
Now lets assume we have another option of making clear what the variable is for... eehmm...
//TODO: Say something wiseguyish about documentation..
Ralph | mailto:ralphAT NOSPAMaffy dot nl | ralphAT NOSPAMaffy dot nl
07/24/2008 12:38 PM
We've used the term "Cargo" for that kind of thing. "I'm just carrying this for someone else, I don't know/care what it is. I'll let them assume any legal responsibilities for what it is and how its used".Starsky
08/03/2008 4:57 AM
I agree; "state" is the best name. Shame it wasn't used throughout the framework. It matches the IAsyncResult.AsyncState property name just fine. Prefixing with "async" does nothing for readability or understandability.More like: if only changing the name of IAsyncResult weren't a breaking change, maybe more people would do async programming!
Pete
11/19/2008 2:11 AM
I always use async calls for I/O (especially sockets) and I tend to have a context object which gets passed through that parameter. It's not always a state so I would vote against anything that says "state" personally. I vote for context as a name because it's a context within which the async calls are operating.I also like Starsky's "cargo" though - it describes what it is very well.
Alan | http://www.benchmarx.com | alan dot kellyAT NOSPAMbenchmarx dot com