【问题标题】:How to know if an async method is running如何知道异步方法是否正在运行
【发布时间】:2026-02-04 04:20:03
【问题描述】:

我有一个按钮,点击事件会从服务器获取数据并将其显示在网格上。

代码如下:

private void btnSearch_Click(object sender, EventArgs e)
{
    // Here I should do something in order to know if the async ProcessSearch method is busy..
    // if not busy then I will execute it if not then I will return.
    // shows loading animation
    ShowPleaseWait(Translate("Searching data. Please wait..."));
    ProcessSearch();
}

private async void ProcessSearch()
{
    Data.SeekWCF seekWcf = new Data.SeekWCF();
    _ds = await seekWcf.SearchInvoiceAdminAsync(new Guid(cboEmployer.Value.ToString()), new Guid(cboGroup.Value.ToString()), txtSearchInvoiceNumber.Text, chkSearchLike.Checked, txtSearchFolio.Text, Convert.ToInt32(txtYear.Value));
    seekWcf.Dispose();

    if (_ds != null)
    {
        SetupInvoiceGrid();
    }
    // hides the loading animation
    HidePleaseWait();
}

我如何知道异步方法 ProcessSearch 是忙还是正在运行,这样我就可以防止用户在再次单击按钮时再次执行该方法。

【问题讨论】:

  • 顺便说一句,你应该只在顶层使用async void。也就是说,ProcessSearch() 应该是 async Task 方法,btnSearch_Click 应该是 async void 方法,awaits 是 ProcessSearch() 的结果。

标签: c# multithreading task-parallel-library async-await


【解决方案1】:

你可以设置一个布尔值:

private bool isSearching = false;

private void btnSearch_Click(object sender, EventArgs e)
{
    if (isSearching)
        return;
    // shows loading animation
    ShowPleaseWait(Translate("Searching data. Please wait..."));
    ProcessSearch();
}

private async void ProcessSearch()
{
    isSearching = true;

    // do other stuff

    isSearching = false;
}

如果您担心并发,可以添加lock

private bool isSearching = false;
private object lockObj = new object();

private void btnSearch_Click(object sender, EventArgs e)
{
    lock (lockObj)
    {
        if (isSearching)
            return;
        else
            isSearching = true;
    }
    // shows loading animation
    ShowPleaseWait(Translate("Searching data. Please wait..."));
    ProcessSearch();
}

private async void ProcessSearch()
{
    // do other stuff

    isSearching = false;
}

【讨论】:

  • 异步运算符中没有内置的“IsBusy”属性还是什么?喜欢 BackgroundWorkers?
  • 从技术上讲,这段代码很容易出现竞争条件。虽然不太可能发生,但您应该使用锁来保护自己。
  • @VAAA 有Task.IsCompleted,但要使用它,您必须将其设为private async Task ProcessSearch() 并将该任务存储在字段中; IMO 只存储一个布尔值更简单。
  • @BrokenGlass 只要 btnSearch_Click 仅从 UI 线程调用,我认为这里没有潜在的竞争条件。我可能是错的。
  • @BrokenGlass 我将如何使用锁?这对我来说是新事物。欣赏它