You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinForm中调用异步数据库方法等待结果完成的问题

问题描述

我之前看过相关讨论,但那些方案都没用。在我的WinForm应用里,数据库查询只能通过异步方法实现,我需要确保myObjectsList被查询结果填充后,再调用DisplayInTheDatagridview(myObjectsList)。但目前调用该方法时传入的始终是空列表,设置断点等待一会儿就能获取到数据库中的目标数据。我尝试过以下几种实现方式:

public void ShowRowsInDatagridview(List<MyObjects> listRowsToQueryDB)
{
    List<MyObjects> myObjectsList = new List<MyObjects>();

    var task = client.GetListFromDBAsync(listRowsToQueryDB);
    task.Wait();

    var result = task.Result;
    myObjectsList = (List<MyObjects>)result;

    DisplayInTheDatagridview(myObjectsList);
}

public void ShowRowsInDatagridview(List<MyObjects> listRowsToQueryDB)
{
    List<MyObjects> myObjectsList = new List<MyObjects>();

    var result = client.GetListFromDBAsync(listRowsToQueryDB).GetAwaiter().GetResult();
    myObjectsList = (List<MyObjects>)result;

    DisplayInTheDatagridview(myObjectsList);
}

public void ShowRowsInDatagridview(List<MyObjects> listRowsToQueryDB)
{
    List<MyObjects> myObjectsList = new List<MyObjects>();

    var result = Task.Run(async () => await client.GetListFromDBAsync(listRowsToQueryDB)).Result;
    myObjectsList = (List<MyObjects>)result;

    DisplayInTheDatagridview(myObjectsList);
}
解决方案

WinForm里直接用Wait()、Result这类阻塞方法很容易触发UI线程死锁,这就是你拿不到数据的核心原因——异步操作被阻塞,根本没机会完成。正确的做法是用async/await模式,同时保证UI线程安全:

正确实现代码

如果是按钮点击这类事件触发的方法,用async void:

private async void ShowRowsInDatagridview(List<MyObjects> listRowsToQueryDB)
{
    // 用await等待异步查询,不会阻塞UI线程
    var myObjectsList = await client.GetListFromDBAsync(listRowsToQueryDB) as List<MyObjects>;
    
    // 确保在UI线程更新DataGridView(await后默认回到UI线程,这步是保险操作)
    if (dataGridView1.InvokeRequired)
    {
        dataGridView1.Invoke(new Action(() => DisplayInTheDatagridview(myObjectsList)));
    }
    else
    {
        DisplayInTheDatagridview(myObjectsList);
    }
}

如果是普通工具方法,推荐用async Task:

private async Task ShowRowsInDatagridviewAsync(List<MyObjects> listRowsToQueryDB)
{
    var myObjectsList = await client.GetListFromDBAsync(listRowsToQueryDB) as List<MyObjects>;
    
    if (dataGridView1.InvokeRequired)
    {
        dataGridView1.Invoke(new Action(() => DisplayInTheDatagridview(myObjectsList)));
    }
    else
    {
        DisplayInTheDatagridview(myObjectsList);
    }
}

关键说明

  • await会释放当前UI线程,让异步查询在后台执行,完成后自动切回UI线程(从UI线程发起的await默认会回到UI线程)
  • 绝对不要用Wait()、Result这类阻塞方法,它们会让UI线程和异步操作互相等待,直接卡死异步流程
  • 如果你断点等待能拿到数据,说明GetListFromDBAsync本身没问题,就是死锁导致异步操作没机会完成

内容的提问来源于stack exchange,提问作者Tech develop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 14:16:31