在Windows窗体中使用以下代码。
private bool test = false;
private async void button1_Click(object sender, EventArgs e)
{
await Task.Run(() =>
{
test = !test ;
textBox2.Text = test.ToString(); // Each time i click text box switches to true and false
for (int i = 0; i < 1000000; i++)
{
textBox1.Text = i.ToString();
}
});
textBox2.Text = "Done"; // This will never happen until the task is done
}
如果我单击按钮,文本框文本将从0更改为1000000。
因为我使用async / await。表单不会冻结,我可以看到文本框计数从0到1000000。
但问题是,如果我再次单击该按钮,另一个线程生成和文本框值将由两个线程更改。你可以看到两个线程改变文本框值的两个计数器。
如果再次点击,你会得到3个主题,4个主题等等....另外textbox2也会变为true,false,true ....
这对我来说只是一个测试,看看实际异步等待是如何工作的。
但我认为我错了。我担心如果我在我的项目中使用异步并结束这种情况。
如何从单一异步方法中停止产生线程。
目前我认为每次按下按钮New async Method都会产生。
这就是我所看到的。
答案 0 :(得分:1)
关于正在发生的事情的评论中存在一些混淆。特别是因为发布的代码实际上不起作用(它不是线程安全的)。
重现此方法的最简单方法(在表单上删除Button和Label):
private async void button1_Click(object sender, EventArgs e) // add the async
{
for (int i = 0; i < 1000; i++)
{
label1.Text = "" + i;
await Task.Delay(100);
}
}
您可以让它一次运行多个循环,您可以增加延迟以更好地查看。请注意,没有涉及额外的线程,它都在主GUI线程上运行。
这里的密钥是async
和await
,它们使编译器将对此方法的调用转换为状态机,这样它就可以一次交错执行多个循环。可以将其视为可以在await
调用时暂停并稍后恢复的方法。所有都在同一个线程上。
更重要的是,它将循环与主线程交错,以便继续处理输入消息并更新屏幕。
那是“为什么”的一部分。
如何解决它的部分取决于你真正想要的,@ CSharpie现在删除的答案显示基本模式:使用布尔字段作为保护,或禁用&amp;启用按钮。
答案 1 :(得分:0)
按下后禁用按钮,并在完成后启用它。