"await/async": Why the 2 pieces of code doesn't run the same?
async-await, asynchronous, c#, c#-5.0, task-parallel-library
Solution
This is explained in the C# language specification. Section 14.3.2: Compound Assignment:
[T]he operation is evaluated as x = x op y, except that x is evaluated only once.
The line
this.async_lbl.Text += await wait_task;
expands to
this.async_lbl.Text = this.async_lbl.Text + await wait_task;
At the time the line is executed, `this.async_lbl.Text` is the empty string. The right hand side therefore evaluates to
"" + await wait_task
The code then awaits the result of the task, and it returns 4. The result of the expression is therefore
"" + "4"
which is `"4"`. which is then assigned as the text of `this.async_lbl`. Notice that the starting value of `this.async_lbl.Text` is used before the `await` occurs.
On the other hand,
string wait_value = await wait_task;
this.async_lbl.Text += wait_value;
expands to
string wait_value = await wait_task;
this.async_lbl.Text = this.async_lbl.Text + wait_value;
This time, the code awaits the `wait_task`, which returns `"4"`. But in the meantime, the value of `this.async_lbl.Text` changed to `"3"`. Then the line
this.async_lbl.Text = this.async_lbl.Text + wait_value;
executes, and the right-hand side is now
"3" + "4"
which evaluates to `"34`".
Problem
It's a simple WinForm application to experiment with the await/async keywords. Below is the event handler for a button. I quickly click the button twice, the interval is smaller than 3000ms so the background threads are not done yet. ``` private Task<String> f() { return Task.Run<String>(() => { Thread.Sleep(3000); return Thread.CurrentThread.ManagedThreadId.ToString(); } ); } private async void async_btn_Click(object sender, EventArgs e) { Task<String> wait_task = f(); //Code 1, this outputs first 3, and then 3 is REPLACED with 4. //this.async_lbl.Text += await wait_task; //3 -> 4 //Code 2, this outputs first 3, and then 34. //String wait_value = await wait_task; //this.async_lbl.Text += wait_value; //3 -> 34 } ``` Why the output of 1 and 2 differ? Thanks! ADD Below is the reflected code: 3 -> 34 ``` // WindowsFormsApplication1.Form1 private async void async_btn_Click(object sender, EventArgs e) { Task<string> task = this.f(); string str = await task; Label expr_AA = this.async_lbl; expr_AA.Text += str; } ``` 3 -> 4 ``` // WindowsFormsApplication1.Form1 private async void async_btn_Click(object sender, EventArgs e) { Task<string> task = this.f(); Label label = this.async_lbl; label.Text += await task; } ```