【问题标题】:Converting to async,await using async targeting package使用异步目标包转换为异步,等待
【发布时间】:2012-12-02 22:32:09
【问题描述】:

我有这个:

private void BtnCheckClick(object sender, EventArgs e)
{
        var a = txtLot.Text;
        var b = cmbMcu.SelectedItem.ToString();
        var c = cmbLocn.SelectedItem.ToString();
        btnCheck.BackColor = Color.Red;
        var task = Task.Factory.StartNew(() => 
                           Dal.GetLotAvailabilityF41021(a, b, c));
        task.ContinueWith(t =>
        {
                btnCheck.BackColor = Color.Transparent;
                lblDescriptionValue.Text = t.Result.Description;
                lblItemCodeValue.Text = t.Result.Code;
                lblQuantityValue.Text = t.Result.AvailableQuantity.ToString();
        },TaskScheduler .FromCurrentSynchronizationContext() );
        LotFocus(true);
}

我按照 J. Skeet 的建议进入异步,在我的 .NET 4.0 应用程序中等待。我转换成这个:

private async void BtnCheckClick(object sender, EventArgs e)
{
        var a = txtLot.Text;
        var b = cmbMcu.SelectedItem.ToString();
        var c = cmbLocn.SelectedItem.ToString();
        btnCheck.BackColor = Color.Red;
        JDEItemLotAvailability itm = await Task.Factory.StartNew(() => Dal.GetLotAvailabilityF41021(a, b, c));
        btnCheck.BackColor = Color.Transparent;
        lblDescriptionValue.Text = itm.Description;
        lblItemCodeValue.Text = itm.Code;
        lblQuantityValue.Text = itm.AvailableQuantity.ToString();
        LotFocus(true);
}

它工作正常。让我感到困惑的是,我可以在不使用 Task 的情况下做到这一点,而只需使用我的 Dal 的方法。但这意味着我必须修改我的 Dal 方法,这是我不想要的?

如果有人能用“简单”的语言向我解释我所做的是否是最佳的以及为什么,我将不胜感激。

谢谢

附:我的dal方法

public bool CheckLotExistF41021(string _lot, string _mcu, string _locn)
{
        using (OleDbConnection con = new OleDbConnection(this.conString))
        {
                OleDbCommand cmd = new OleDbCommand();
                cmd.CommandText = "select lilotn from proddta.f41021 " +
                                        "where lilotn = ? and trim(limcu) = ? and lilocn= ?";
                cmd.Parameters.AddWithValue("@lotn", _lot);
                cmd.Parameters.AddWithValue("@mcu", _mcu);
                cmd.Parameters.AddWithValue("@locn", _locn);
                cmd.Connection = con;
                con.Open();
                OleDbDataReader rdr = cmd.ExecuteReader();
                bool _retval = rdr.HasRows;
                rdr.Close();
                con.Close();
                return _retval;
        }
}

【问题讨论】:

  • 你能显示一些 dal 代码吗?为什么以及如何改变它?
  • 它是一个带有 OleDbconnection 的简单 OledbDataReader。改变我说如果没有使用任务,我将不得不用异步装饰我的 dal 方法并等待获取语句?
  • @ArsenMkrt:我添加了 dal 方法。

标签: c# .net multithreading async-await


【解决方案1】:

不,这根本不是最佳选择。如果您无法将 DAL 层更改为异步,则使用 async/await 不会获得太多收益。您只是在单独的后台线程中运行您的阻塞 DAL 方法。如果你想要真正的收益,你应该修改你的 DAL 方法以使用异步 ADO.NET,a.k.a BeginXXX 和 EndXXX 方法。一旦你这样做了,你将从 I/O 完成端口中获得真正的好处。在执行数据库调用期间,任何线程都不会受到危害。

如果你不能修改你的 DAL 方法,无论你是使用JDEItemLotAvailability itm = await Task.Factory.StartNew(() => Dal.GetLotAvailabilityF41021(a, b, c)); 还是手动创建线程,真的,你什么都得不到。

【讨论】:

  • 我明白了。在这个特定的应用程序(非常简单)中,我主要关心的是在执行 dal 操作时不要让我的主窗体锁定。这些dal操作非常简单快捷。谢谢。
  • 好吧,那么在单独的线程中运行它们对你来说应该足够了。您将不再阻塞主线程。但是,由于您询问了最佳解决方案,就您而言,这将是修改您的 DAL 方法以使用异步 ADO.NET。
  • 它是“不是最佳的”,因为它会在数据库操作进行时占用线程池线程。但从某种意义上说,它是完全“最佳”的,因为它实现了 GUI 应用程序中async 操作的主要目标:提高响应能力。
  • @StephenCleary,当然,我只是说在这种情况下使用 async/await 没有任何好处。您可以使用标准的后台线程。我在回答中试图澄清的是 async/await 不是魔术棒。这两个关键字不会自动为任何现有代码带来任何好处。它们正在简化语法,并且只是已经编写好的异步代码的语法糖。很多人都被愚弄了,我会在我的代码中加入那些 async/await 关键字,我会改进我的传统同步 I/O 调用。不,那是神话。
  • 不清楚你所说的正确是什么意思。目前您正在正确使用它们。你的代码没有问题。但这不是最佳解决方案。如果您想要最佳解决方案,那与任何 TPL 或任何 async/await 完全无关。您必须修改 DAL 方法以使用 BeginXXX 和 EndXXX ADO.NET 方法。这是第一步。然后很容易包装在 TPL 和 async/await 中。但是如果没有真正的异步 DB 调用,您将一无所获。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-22
相关资源
最近更新 更多