首页 > 解决方案 > 计算异步按钮被按下的次数(或者是否正在进行某些操作)

问题描述

我知道对于异步操作,可以跟踪其进度,但我稍后会尝试。现在我有一个简单的窗口窗体应用一个按钮(或一对按钮 - 数字无关紧要)。按钮调用异步操作

public async void Button1_Click(...)
{
   await Button1_OperationAsync(...);
}

如果我不按下按钮,什么都不会发生,但如果我在Button1_OperationAsync启动时按下它(并且正在等待)。(我不确定是否称其为“线程”)。

但是如果我按两次按钮会发生什么?那么在第一个异步操作完成之前,Button1_OperationAsync再次调用了。(或者如果按下另一个类似的按钮,则Button2_OperationAsync调用 a)

甚至可能第二个异步操作会在第一个异步操作之前完成。

我想要的是一种简单的方法来了解是否正在进行任何操作。所以我的想法是有一个变量并在调用操作时增加它,并在操作完成时减少它。就像是

int numberOfOps=0;
public async void Button1_Click(...)
{  numberOfOps++;
   textBox1.Text="Started!";
   await Button1_OpeationAsync(...);
   numberOfOps--;
   if(numberOfOps<=0) 
     {
      textBox1.Text="Done!";
     }
}

请注意,此代码也将进入另一个按钮 (Button2)。或许多其他按钮。

我知道可能涉及同步问题。因此,我将不胜感激有关我正在尝试做的事情的建议,以便正确地做

标签: c#async-await

解决方案


使用async/await时,除了 UI 线程之外,您没有为 UI 代码使用任何线程。在Button1_OpeationAsync方法中调用的代码可能使用单独的线程,但调用代码将保留在 UI 线程上。

尝试使用以下代码:

private int numberOfOps = 0;

private async void button1_Click(object sender, EventArgs e)
{
    textBox1.Text = $"Started! {++numberOfOps}";
    await Task.Delay(TimeSpan.FromSeconds(5.0));
    textBox1.Text = $"Started! {--numberOfOps}";
    if (numberOfOps == 0)
    {
        textBox1.Text = "Done!";
    }
}

它工作得很好。您可以numberOfOps跨多个按钮使用该变量。

如果您想让重用代码变得容易,请尝试以下方式:

    int numberOfOps = 0;

    private async Task RunOp(Func<Task> op)
    {
        textBox1.Text = $"Started! {++numberOfOps}";
        await op();
        textBox1.Text = $"Started! {--numberOfOps}";
        if (numberOfOps == 0)
        {
            textBox1.Text = "Done!";
        }
    }

    private async void button1_Click(object sender, EventArgs e)
    {
        await this.RunOp(() => Button1_OpeationAsync(...));
    }

    private async void button2_Click(object sender, EventArgs e)
    {
        await this.RunOp(() => Button2_OpeationAsync(...));
    }

推荐阅读