【问题标题】:using await in WPF application在 WPF 应用程序中使用 await
【发布时间】:2016-01-29 14:50:41
【问题描述】:

我正在尝试在 c# 中执行异步功能。我能够使用此代码获得它:

private async Task loadData()
{
     try
     {
         await Task.Run(() => { testTableAdapter.Fill(testDataSet.tbl); });
     }
     catch (Exception ex)
     {
         MessageBox.Show(ex.ToString());
     }
}

但由于我试图访问 UI 控件,因此我尝试在不执行 Task.Run 的情况下执行此操作(因此我没有启动新的工作线程),并且我收到了一个我不理解或怎么修。

private async Task loadData()
{
     try
     {
          await  testTableAdapter.Fill(testDataSet.tbl); 
          perComboBox.text = loadedSearch.toString();
     }
     catch (Exception ex)
     {
          MessageBox.Show(ex.ToString());
     }
}

错误是:

严重性代码描述项目文件行错误 CS1061 'int' 确实 不包含“GetAwaiter”的定义,也没有扩展方法 可以找到接受“int”类型的第一个参数的“GetAwaiter” (您是否缺少 using 指令或程序集引用?)

【问题讨论】:

  • 看来问题出在您省略的// code 位上。在没有更多上下文的情况下,不清楚您在这里真正想要做什么。
  • 它是一个数据集填充,我编辑了 OP。对不起!
  • 对,所以问题是这是一个同步操作。您不能使用 async/await 神奇地使同步操作异步。现在,您尝试在该代码的哪个位置访问 UI 控件?
  • 它只是更改组合框文本的值,但错误发生在等待时。有没有你知道的异步填充数据集?
  • 什么在改变组合框的值?这是绑定到数据表的组合框吗?也许您应该取消绑定,填充,然后重新绑定...

标签: c# wpf asynchronous task


【解决方案1】:

这是您的解决方案。请阅读更多 Stephen Cleary 主页提供的内容。使用异步时,线程和后台工作人员已过时。根据您使用LoadData 的位置,提供同步方法总是一个好主意。然后,您可以根据实现将其包装成异步的。您真的应该从适当的 DataAccessLayer 取回 TableAdaper 结果。记住关注点分离。

将您的方法更改为:

private int LoadData()
{
    try
    {
        return testTableAdapter.Fill(testDataSet.tbl); 
    }
    catch (Exception ex)
    {
         MessageBox.Show(ex.ToString());
    }

    return -1;
}

现在是调用类中的异步包装器。实际上,异步部分应该在窗口加载或其他 GUI 事件中。下面是一个可以填充数据的按钮单击示例。 .ConfigureAwait(false) 表示等待者将被发送到调度程序而不是在 GUI 线程上执行。还可以考虑将 MVVM 用于 WPF。我想指出,如果您的 Window_Closing 事件被调用,_cToken 的 CancellationTokenSource 将设置为 Cancel()。这是为了确保您的异步操作得到清理。

private async void _btnTruck_OnClick(object sender, RoutedEventArgs e)
{
    int count = 0;

    try
    {
        count = await Task.Run(() => LoadData(), _cToken).ConfigureAwait(false);
        perComboBox.text = loadedSearch.toString();
    }
    catch (Exception ex)
    {
        _log.Error(ex); 
    }
}

【讨论】:

  • 试过了,cancellationToken 出错,说 'CancellationToken' 是一种类型,在给定的上下文中无效
  • 尝试传入CancellationToken.None 而不仅仅是CancellationToken
  • 代码示例假设您的表单上有一个名为CancellationToken 的属性
  • 请记住,如果您使用ConfigureAwait(false),那么在调用之后您将无法对 UI 执行任何其他操作。因此,例如,如果您想在问题中使用perComboBox.text = loadedSearch.toString();,现在就不能了。
  • .ConfigureAwait() 定义了等待者的维护位置。 True 表示调用线程维护它,false 表示将其发送到调度程序。如果设置为 false,它将不会限制与 GUI 的交互。考虑一下,如果您的 GUI 线程超载,然后调用异步代码,则它必须维护等待程序,并对其施加额外压力以跟踪幕后的同步对象。
猜你喜欢
  • 2021-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多