异步按钮单击处理程序为每次调用维护单独的局部变量是什么机制?

问题描述 投票:0回答:2

此代码执行您所期望的操作:快速连续单击两次按钮将启动两个任务并使用两个不同的局部变量值打印两条消息。

private bool _dummy;
        
private async void button1_Click(object sender, EventArgs e)
{
  int a;
  if (_dummy == false)
  { 
    a = 1; 
    _dummy = true; 
  }
  else
  { 
    a = 99;
    _dummy = false;
  }

  Debug.WriteLine($"{DateTime.Now:HH:mm:ss:fff} {Thread.CurrentThread.ManagedThreadId} {a} click pre delay");
  Task dtask = Task.Delay(2000);
  await dtask;
  Debug.WriteLine($"{DateTime.Now:HH:mm:ss:fff} {Thread.CurrentThread.ManagedThreadId} {a} {dtask.Id} click post delay");
}

结果消息:

15:21:52:111 1 1 click pre delay
15:21:52:595 1 99 click pre delay
15:21:54:120 1 1 7 click post delay
15:21:54:615 1 99 9 click post delay

问题是:什么机制可以实现这一点?该方法的第一次等待后恢复如何为本地值维护一个单独的堆栈,并如何与第二次等待后恢复保持分离? 我知道(或者至少有一个模糊的概念)线程具有独立的堆栈,但在这种情况下,所有内容都在单个 GUI 线程上(通过打印

ManagedThreadId

进行验证。)

[这个问题类似于https://stackoverflow.com/questions/54941894/c-sharp-async-how-does-a-thread-remember-its-local-variables,但我不知道我是否会将它们视为真正的重复项。我的问题特别是关于解开

暂时

重叠的调用。]

c# winforms async-await task
2个回答
2
投票
async

调用通过创建状态机来工作。各种状态机(每次调用一个)独立运行并具有各自的独立变量。

看看您的示例被降低到什么程度,例如“

here


2
投票
async

方法创建一个实现状态机的内部类。方法中的局部变量被转换为类的字段。对于该方法的每次调用,都会创建该内部类的一个新实例。

您可以在

https://sharplab.io/#gist:b0bda78721855033b6423b6cd872d05e

查看编译器生成的代码示例

© www.soinside.com 2019 - 2024. All rights reserved.