3

这是一个简单的 WinForm 应用程序,用于试验 await/async 关键字。下面是按钮的事件处理程序。

我快速点击按钮两次,间隔小于 3000ms 所以后台线程还没有完成。

    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
    }

为什么1和2的输出不同?

谢谢!

添加

下面是反映的代码:

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;
}
4

1 回答 1

11

这在 C# 语言规范中进行了解释。第 14.3.2 节:复合赋值

[T]他的操作被评估为 x = x op y,除了 x 只被评估一次。

线

this.async_lbl.Text += await wait_task;

扩展到

this.async_lbl.Text = this.async_lbl.Text + await wait_task;

在执行该行时,this.async_lbl.Text是空字符串。因此,右侧计算为

"" + await wait_task

然后代码等待任务的结果,并返回 4。因此,表达式的结果是

"" + "4"

这是"4"。然后将其分配为 的文本this.async_lbl。请注意,在发生之前this.async_lbl.Text使用的起始值。await

另一方面,

string wait_value = await wait_task;
this.async_lbl.Text += wait_value;

扩展到

string wait_value = await wait_task;
this.async_lbl.Text = this.async_lbl.Text + wait_value;

这一次,代码等待wait_task返回"4". 但与此同时, 的值this.async_lbl.Text变为"3"。然后线

this.async_lbl.Text = this.async_lbl.Text + wait_value;

执行,右边是现在

"3" + "4"

评估为"34“。

于 2013-03-31T16:43:45.690 回答