如何将元组转换为异步任务

时间:2019-03-26 17:24:59

标签: c# async-await tuples task

我正在做一个小型应用程序,需要帮助,因为我不知道问题出在哪里。

我已经很长时间没有使用C#了,而且我正在一点一点地学习,因为所有这些都是我的闲暇,而已。

我有以下运行正常的元组:

private Tuple<int, int, int, int> CheckStatus()
        {
            int out = 0;
            int stage = 0;
            int retired = 0;
            int stop = 0;
            for (int i = 0; i < Dgv.Rows.Count; i++)
            {
                if (Dgv.Rows[i].Cells["Start"].Value != null)
                {
                    out = out + 1;
                }
                if (Dgv.Rows[i].Cells["Start"].Value != null && Dgv.Rows[i].Cells["Finnish"].Value == null)
                {
                    stage = stage + 1;
                }
                if (Dgv.Rows[i].Cells["Start"].Value != null && Dgv.Rows[i].Cells["Finnish"].Value != null)
                {
                    stop = stop + 1;
                }
            }
            retired = GetRetirements();
            stage = stage - retired;
            return new Tuple<int, int, int,int>(out, stage, retired, stop);
        }

我想将其传递给异步以执行await方法,因为现在GetRetirements方法是异步任务,并将代码更改为此,但是我遇到了问题:

private async Task<Tuple<int, int, int, int>> CheckStatus()
        {
            int out = 0;
            int stage = 0;
            int retired = 0;
            int stop = 0;
            for (int i = 0; i < Dgv.Rows.Count; i++)
            {
                if (Dgv.Rows[i].Cells["Start"].Value != null)
                {
                    out = out + 1;
                }
                if (Dgv.Rows[i].Cells["Start"].Value != null && Dgv.Rows[i].Cells["Finnish"].Value == null)
                {
                    stage = stage + 1;
                }
                if (Dgv.Rows[i].Cells["Start"].Value != null && Dgv.Rows[i].Cells["Finnish"].Value != null)
                {
                    stop = stop + 1;
                }
            }
            retired = await GetRetirements();
            stage = stage - retired;
            return new Tuple<int, int, int,int>(out, stage, retired, stop);
        }

但是告诉我找不到任何项目(item1,item2,item3,item4)。我不知道问题出在哪里。

private void GetCheckStatus()
        {
            LblOut.Text = CheckStatus().Item1.ToString();
            LblStage.Text = CheckStatus().Item2.ToString();
            LblRetired.Text = CheckStatus().Item3.ToString();
            LblStop.Text = CheckStatus().Item4.ToString();
        }

我做错了什么?这是我第一次与Tuple合作,但我不知道这可能是错的事实。

非常感谢您。

最诚挚的问候,

4 个答案:

答案 0 :(得分:2)

CheckStatus现在是一个异步函数。要获得结果,您需要await,并且您可能只想调用一次函数。请注意,async如何也已添加到GetCheckStatus中,并将一直流到async void事件处理程序,例如单击按钮。

private async Task GetCheckStatus()
{
    var status = await CheckStatus()
    LblOut.Text = status.Item1.ToString();
    LblStage.Text = status.Item2.ToString();
    LblRetired.Text = status.Item3.ToString();
    LblStop.Text = status.Item4.ToString();
}

答案 1 :(得分:1)

您将CheckStatus()更改为返回Task<>。您可能应该await并像以前一样使用结果。

您还可以根据UI框架以不同的方式处理它。但是归结为“此方法现在是aysnc,以这种方式处理”。

答案 2 :(得分:1)

您已使内部调用异步,但外部调用没有等待它。尝试类似的东西:

private async Task GetCheckStatus()
{
    var result = await CheckStatus();

    LblOut.Text = result .Item1.ToString();
    LblStage.Text = result .Item2.ToString();
    LblRetired.Text = result .Item3.ToString();
    LblStop.Text = result .Item4.ToString();
}

答案 3 :(得分:0)

原因是,在访问结果之前,您忘记等待CheckStatus()的结果。

以async结束async函数的名称是很常规的。这是为了警告用户不要忘记他们正在使用async-await,并且在访问结果之前,他们应该等待返回值。

这还有一个优势,您可以同时提供普通版和异步版

async Task<int> GetRetirementsAsync(){...}

async Task<Tuple<int, int, int, int>> CheckStatusAsync()
{
     ...
     int retired = await GetRetirementsAsync();
     return new Tuple...
}

async Task GetCheckStatusAsync()
{
    var tuple = await CheckStatusAsync();

    // process output:
    LblOut.Text = tuple.Item1.ToString();
    LblStage.Text = tuple.Item2.ToString();
    LblRetired.Text = tuple.Item3.ToString();
    LblStop.Text = tuple.Item4.ToString();
}

可能的性能改进

您想要使用GetRetirementsAsync而不是非异步GetRetirements的原因是,因为您期望该流程内部的某个地方必须闲置地等待另一个流程的结果,例如查询数据库或读取文件,或从互联网上获取数据。

您可以使用async await来完成其他事情,而无需真正等待数据库,直到真正需要数据库中的结果为止。

您可以通过启动任务来执行此操作,而无需等待。线程不会闲着等待数据库,而是继续处理您的语句,直到需要结果并等待任务为止。

private async Task<Tuple<int, int, int, int>> CheckStatus()
{
    // Get the retirements, do not await yet.
    Task<int> taskGetRetirements = GetRetirementsAsync();

    // instead of waiting idly, your thread is free to do the following:
    int out = 0;
    int stage = 0;
    int retired = 0;
    int stop = 0;
    for (int i = 0; i < Dgv.Rows.Count; i++)
    {
        ...
    }

    // now you need the retirements; await for the task to finish
    int retired = await taskGetRetirements;
    stage = stage - retired;
    return new Tuple<int, int, int,int>(out, stage, retired, stop);
}