C# 阻止线程繁殖
在Windows窗体中具有下面的代码C# 阻止线程繁殖,c#,multithreading,asynchronous,C#,Multithreading,Asynchronous,在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
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
}
private bool test=false;
私有异步无效按钮1\u单击(对象发送方,事件参数e)
{
等待任务。运行(()=>
{
测试=!测试;
textBox2.Text=test.ToString();//每次单击时,文本框都会切换为true和false
对于(int i=0;i<1000000;i++)
{
textBox1.Text=i.ToString();
}
});
textBox2.Text=“Done”;//在任务完成之前,这种情况永远不会发生
}
如果单击按钮,文本框文本将从0更改为1000000
因为我使用异步/等待。表单不会冻结,我可以看到文本框从0到1000000计数
但问题是,如果我再次单击该按钮,则会生成另一个线程,textbox值会更改两个线程。您可以看到两个线程中的两个计数器正在更改textbox值
如果再次单击,则会得到3个线程、4个线程等…textbox2也会更改为true、false、true
这对我来说只是一个测试,看看async await实际上是如何工作的
但我认为我用错了。我担心如果我在项目中使用async,最终会出现这种情况
如何停止从单个异步方法生成线程
目前,我认为每次按下按钮都会产生新的异步方法
这是我看到的
按下按钮后禁用该按钮,并在按钮完成后启用。评论中对正在发生的事情有一些混淆。特别是因为发布的代码实际上不应该工作(它不是线程安全的) 最简单的复制方法(在表单上放置按钮和标签):
private async void按钮1\u单击(对象发送方,事件参数)//添加异步
{
对于(int i=0;i<1000;i++)
{
标签1.Text=”“+i;
等待任务。延迟(100);
}
}
您可以让它一次运行多个循环,您可以增加延迟以更好地看到这一点。请注意,没有涉及额外的线程,所有线程都在主GUI线程上运行
这里的键是async
和wait
,它们使编译器将对该方法的调用转换为状态机,这样它就可以一次交错执行多个循环。可以将其视为一种可以在wait
调用时暂停并稍后恢复的方法。都在同一条线上
更重要的是,它将循环与主线程交错,以便继续处理输入消息并更新屏幕
这就是为什么
如何解决这一问题取决于您实际需要什么,现在从@CSharpie删除的答案显示了基本模式:使用布尔字段作为保护,或者禁用并启用按钮 还是说吧。最好的办法是。因为我所做的是错误的编码风格。异步方法就是这样做的。用户界面应该根据最终结果而不是多任务来更新。非常感谢。我不知道我能像这样运行这个方法。异步与我的想法完全不同。并且从Task.Run.com开始,仅对事件处理程序使用
async void
模式。在其他地方,使用异步任务
。这是完全不同的代码。我已经知道这是可能的,但是您正在UI线程上运行分配,并且没有任务。运行。在OP的代码中,要么整个lambda在单独的线程上运行(在这种情况下,它们应该得到一个错误),要么不是(在这种情况下,它们不应该看到竞争线程)。我感兴趣的是OP的代码是如何导致他们所描述的行为的。@Asad-你一路上遇到了一个不同的问题。您可以在调试器之外运行原始代码(Ctrl+F5)。它不是线程安全的,但当您以这种方式禁用检查时,不会发生可怕的事情。这个答案显示了线程安全(无线程)版本显示了相同的核心问题。啊,好吧,这更有意义。我没有意识到只有在调试模式下才会发生这种异常。
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);
}
}