C# 等待异步后台线程行为

问题描述 投票:0回答:1

我正在更新一个 C# WPF 项目,该项目之前使用 WCF 服务,现在调用基于 REST 的 API。

以下代码是 REST API 调用的典型示例:

public static async Task<List<KBase>> GetKbase(int shopID)
{
    // set request
    string uri = ROOT_URI + "kbase/" + shopID.ToString();
    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri);
    request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", access_token.token);

    // get
    HttpResponseMessage response = await http_client.SendAsync(request);
    if (response.IsSuccessStatusCode)
    {
        string result = response.Content.ReadAsStringAsync().Result;
        List<KBase> kb = JsonConvert.DeserializeObject<List<KBase>>(result);
        return kb;
    }
    else
    {
        string result = response.Content.ReadAsStringAsync().Result;
        gFunc.AddLogEntry("Get Kbase: " + result);
    }
    return null;
}

如果我使用以下代码调用上述 API 方法,一切都会按预期发生。消息框显示 true

private async void btnTest_MouseUp(object sender, MouseButtonEventArgs e)
{
   List<Models.API.KBase> kb = await apiSamadhi.GetKbase(1);
   bool is_data = !(kb == null);
   MessageBox.Show(is_data.ToString());
}

但是,程序的许多部分我都使用后台工作人员来保持主 UI 线程的响应能力。我创建后台工作者如下:

BackgroundWorker bgw;
List<Models.API.KBase> kb;
private void InitBGW()
{
   bgw = new BackgroundWorker();
   bgw.DoWork += bgw_DoWork;
   bgw.RunWorkerCompleted += bgw_WorkCompleted;
}

以下代码显示了 DoWork 和 WorkCompleted 方法:

private async void bgw_DoWork(object sender, DoWorkEventArgs e)
{
    kbase = await apiSamadhi.GetKbase(1);
}

private void bgw_WorkCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    bool is_data = !(kbase == null);
    MessageBox.Show(is_data.ToString());
    System.Threading.Thread.Sleep(1000);
    is_data = !(kbase == null);
    MessageBox.Show(is_data.ToString());
}

当 bgw_WorkCompleted 运行时,kbase 为 null,第一个消息框显示 false。然后,在线程休眠一秒钟后,kbase不为空,第二个消息框显示true

这不是我所期望的行为。就像 bgw_DoWork 中的 await 不起作用一样。为什么 bgw_WorkCompleted 在对 API 的“等待”调用完成之前运行?

我错过了什么或者做了什么愚蠢的事情吗?我需要能够在非 UI 线程上运行“等待”API 调用/任务,并能够在任务完成时更新 UI。

c# wpf async-await backgroundworker
1个回答
0
投票

BackgroundWorker
希望
DoWork
处理程序阻塞,但在
async void
的情况下,它会在实际异步操作完成并调用
WorkCompleted
处理程序之前退出 - 这里真正的工作只是 starting 异步操作,而不是等待它完成。
BackgroundWorker
async
/
await
配合不佳。

你可以完全放弃

BackgroundWorker
,这样的事情应该可以解决问题:

private async void InitBGW()
{
    var kbase = await Task.Run(async () => 
        await apiSamadhi
            .GetKbase(1)
            .ConfigureAwait(false));
    var is_data = kbase is not null;
    MessageBox.Show(is_data.ToString());
}
© www.soinside.com 2019 - 2024. All rights reserved.