async

M

mick

private async void btnTest_Click_1(object sender, RoutedEventArgs e)
{
await Task.Factory.StartNew(async () => {
var x = await GetInt();
MessageBox.Show("recieved int " + x.ToString());
});

MessageBox.Show("Finished");
}

private async Task<int> GetInt()
{
return await Task.Factory.StartNew( () => {
System.Threading.Thread.Sleep(5000);
return 999;
});
}

Been messing around with the new async stuff and I've come accross this oddity -

Shouldn't the MessageBox.Show("Finished"); line run only after the awaited Task
above it
has finished? In other words shouldn't it be that Tasks continuation. As it is
the
"Finished" MessageBox is showing straight away. Can someone explain what I'm
missing.

TIA,
mick
 
A

Arne Vajhøj

private async void btnTest_Click_1(object sender, RoutedEventArgs e)
{
await Task.Factory.StartNew(async () => {
var x = await GetInt();
MessageBox.Show("recieved int " + x.ToString());
});

MessageBox.Show("Finished");
}

private async Task<int> GetInt()
{
return await Task.Factory.StartNew( () => {
System.Threading.Thread.Sleep(5000);
return 999;
});
}

Been messing around with the new async stuff and I've come accross this
oddity -

Shouldn't the MessageBox.Show("Finished"); line run only after the
awaited Task above it
has finished? In other words shouldn't it be that Tasks continuation. As
it is the
"Finished" MessageBox is showing straight away. Can someone explain what
I'm missing.

You are starting something async and then you execute
the next line.

Arne
 
M

mick

"Arne Vajhøj" wrote in message
private async void btnTest_Click_1(object sender, RoutedEventArgs e)
{
await Task.Factory.StartNew(async () => {
var x = await GetInt();
MessageBox.Show("recieved int " + x.ToString());
});

MessageBox.Show("Finished");
}

private async Task<int> GetInt()
{
return await Task.Factory.StartNew( () => {
System.Threading.Thread.Sleep(5000);
return 999;
});
}

Been messing around with the new async stuff and I've come accross this
oddity -

Shouldn't the MessageBox.Show("Finished"); line run only after the
awaited Task above it
has finished? In other words shouldn't it be that Tasks continuation. As
it is the
"Finished" MessageBox is showing straight away. Can someone explain what
I'm missing.
You are starting something async and then you execute
the next line.

Yes but I'm awaiting on it as well. Anything after an await is supposed not
to run until the await returns, the same as what happens in the var x = await
GetInt() line.
Is it because I'm not waiting on a resulting variable?

mick
 
A

Arne Vajhøj

"Arne Vajhøj" wrote in message



Yes but I'm awaiting on it as well.
No.

Anything after an await is supposed not
to run until the await returns,

No.

await is not waiting.

You need to either explicit call Wait on the returned
task or implicit wait by using the return value.
the same as what happens in the var x =
await GetInt() line.

No.

There you get the return value.
Is it because I'm not waiting on a resulting variable?

Exactly.

Arne
 
M

mick

"Peter Duniho" wrote in message

Yes but I'm awaiting on it as well. Anything after an await is supposed not
to run until the await returns, the same as what happens in the var x = await
GetInt() line.
Is it because I'm not waiting on a resulting variable?
I was in favor of the "await" keyword when it was proposed as the syntax
for this feature. But I wonder if maybe it's implying the wrong thing.
The "await" keyword is actually in some sense the _opposite_ of waiting.
It really means "return from this method right now, and come back to it
later when this other thing is done". The "async" keyword changes the
meaning of a method's return type as well, causing whatever the method
ordinarily would return to be wrapped in a Task.

Yes, I knew that the await didn't mean wait. I just didn't understand the subtle
difference
between Task.Factory.StartNew() and Task.Run() in that the unwrapping is done in
Task.Run.
I must admit I thought they were equivalent and that Task.Factory was left over
from the ctp.
Using Task.Run produces the result I was expecting.
In your example, the call to StartNew() in the click handler starts a new
task, the purpose of which is to return not void, but a Task. The Task is
available as soon as that anonymous async task returns the first time, and
so the task that you started completes at that time, not when the task
actually finishes.
You should be able to see this more clearly by assigning the result of the
"await...StartNew..." to a "var" variable and inspecting the type of the
variable.

Yes I knew it was returning a Task I just thought that awaiting on it meant that
the MB.Show "Finished" would, in effect become that Tasks continuation and not
run
until the Task had completed. The fact that it doesn't work this way suggests
that, effectively -

await Task.Factory.StartNew(async () => {
var x = await GetInt();
MessageBox.Show("recieved int " + x.ToString());
});

is the same as

Task.Factory.StartNew(async () => {
var x = await GetInt();
MessageBox.Show("recieved int " + x.ToString());
});

and the await in the first example doesn't do anything
I think you should be able to get the effect you're looking for by then
awaiting on that returned Task (i.e. a second await, awaiting on the result
of the first await).

Isn't that what I've done? I'm not clear what you mean here. Could you show me.
Also, this web page might help clarify things a bit, as part of its focus
is on this precise issue:
http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx

Yes, thanks, I'm reading through it now.

Changing what I had to the code below does what I at least was expecting.

private async void btnTest_Click_1(object sender, RoutedEventArgs e)
{
await Task.Factory.Run(async () => {
var x = await GetInt();
MessageBox.Show("recieved int " + x.ToString());
});

MessageBox.Show("Finished");
}

private async Task<int> GetInt()
{
return await Task.Factory.StartNew( () => {
System.Threading.Thread.Sleep(5000);
return 999;
});
}

I think I'm getting there...sort of

mick
 
M

mick

"mick" wrote in message


"Peter Duniho" wrote in message

In your example, the call to StartNew() in the click handler starts a new
task, the purpose of which is to return not void, but a Task. The Task is
available as soon as that anonymous async task returns the first time, and
so the task that you started completes at that time, not when the task
actually finishes.
You should be able to see this more clearly by assigning the result of the
"await...StartNew..." to a "var" variable and inspecting the type of the
variable.
Yes I knew it was returning a Task I just thought that awaiting on it meant
that
the MB.Show "Finished" would, in effect become that Tasks continuation and not
run
until the Task had completed. The fact that it doesn't work this way suggests
that, effectively -


Just had a thought after I posted. Is the reason the first await doesnt do what
I thought
because it actually hasnt been unwrapped itself?

mick
 
M

mick

"Peter Duniho" wrote in message

Yes but I'm awaiting on it as well. Anything after an await is supposed not
to run until the await returns, the same as what happens in the var x = await
GetInt() line.
Is it because I'm not waiting on a resulting variable?
I think you should be able to get the effect you're looking for by then
awaiting on that returned Task (i.e. a second await, awaiting on the result
of the first await).

I've just read on in the article. await await - I didn't even know you could
do that. Learn something new everyday. Thanks.

mick
 
A

Arne Vajhøj

I was in favor of the "await" keyword when it was proposed as the syntax
for this feature. But I wonder if maybe it's implying the wrong thing.

The "await" keyword is actually in some sense the _opposite_ of waiting.
It really means "return from this method right now, and come back to it
later when this other thing is done". The "async" keyword changes the
meaning of a method's return type as well, causing whatever the method
ordinarily would return to be wrapped in a Task.

Many have been confused by those keywords.

Eric Lippert wrote in
http://blogs.msdn.com/b/ericlippert...ogramming-in-c-5-0-part-two-whence-await.aspx

<quote>
1) The “async” modifier on the method does not mean “this method is
automatically scheduled to run on a worker thread asynchronously”. It
means the opposite of that; it means “this method contains control flow
that involves awaiting asynchronous operations and will therefore be
rewritten by the compiler into continuation passing style to ensure that
the asynchronous operations can resume this method at the right spot.”
The whole point of async methods it that you stay on the current thread
as much as possible. They’re like coroutines: async methods bring
single-threaded cooperative multitasking to C#. (At a later date I’ll
discuss the reasons behind requiring the async modifier rather than
inferring it.)

2) The “await” operator used twice in that method does not mean “this
method now blocks the current thread until the asynchronous operation
returns”. That would be making the asynchronous operation back into a
synchronous operation, which is precisely what we are attempting to
avoid. Rather, it means the opposite of that; it means “if the task we
are awaiting has not yet completed then sign up the rest of this method
as the continuation of that task, and then return to your caller
immediately; the task will invoke the continuation when it completes.”

It is unfortunate that people’s intuition upon first exposure regarding
what the “async” and “await” contextual keywords mean is frequently the
opposite of their actual meanings. Many attempts to come up with better
keywords failed to find anything better. If you have ideas for a keyword
or combination of keywords that is short, snappy, and gets across the
correct ideas, I am happy to hear them.
</quote>

Arne
 

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

Similar Threads


Top