计算已按下异步按钮的次数(或正在进行某些操作)

时间:2018-07-20 04:30:07

标签: c# async-await

我知道对于异步操作而言,可以跟踪其进度,但是稍后我会尝试。现在,我有一个简单的窗口表单,它带有一个按钮(或一对按钮-数量无关紧要)。这些按钮调用异步操作

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

如果我不按该按钮,则什么也没有做,但是如果我按下该按钮,Button1_OperationAsync一旦启动(并等待)。 (我不确定是否将其称为“线程”)。

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

也许第二个异步操作也将在第一个异步操作之前完成。

我想要的是一种简单的方法来知道是否正在进行任何操作。因此,我认为要有一个变量,在调用操作时将其递增,在操作完成时将其递减。像

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

请注意,此代码也将出现在另一个按钮(Button2)中。或许多其他按钮。

我知道可能会涉及同步问题。因此,我很乐意为正确执行操作提供建议

2 个答案:

答案 0 :(得分:0)

使用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(...));
    }

答案 1 :(得分:-1)

在类级别具有一个任务数组和一个任务对象:

private List<Task> tasks = new List<Task>();
private Task task = null;

在每个点击处理程序中,请执行以下操作:

var operationTask = SomeOperationAsync(...);
tasks.Add(operationTask);
task = Task.WhenAll(tasks);

if (task.IsCompleted)
{
    // no operation is going on
    tasks.Clear();

    // do what ever you want to do further
}
else
{
     //some operation is going on
}