2

我一直在试图弄清楚如何以 Task 类型返回数据,而不是像这样的 int 类型,例如Task<Dictionary<string, string>>.

我似乎找到的所有示例都显示返回一个Task<int>. 这很容易做到return 42;

我一直在尝试编写的函数是这样的:

Task<Dictionary<string, string>> getDamaged()
{
    Task<Dictionary<string, string>> d = new Task<Dictionary<string, string>>();
    Dictionary<string, string> e = new Dictionary<string, string>();

    foreach (Building i in buildingArray)
    {
        if (Convert.ToInt32(i.efficiency) < 100)
        {
            e.Add(i.buildingID, i.buildingName);
            //d.Add(i.buildingID, i.buildingName);  // this does not work, either
        }
    }

我发现Task.FromResult 方法看起来有些有希望,但进一步的调查似乎表明,TResult作为一项已完成的任务,对我来说听起来不一定像你可以做的那样await

关于如何使其正常工作的任何想法?

更新

这种方法的重点是我试图从我的 UI 线程中卸载工作以保持我的 UI 响应。这是我第一次尝试使用带有 .net4.5 的 Visual Studio 2012 来真正尝试做到这一点。上面的代码是我凭记忆写的。我将发布我一直在尝试的实际代码以及注释掉的失败尝试。

真正困扰我的一个部分是,如果我的返回类型是任务,则返回一个 int,但是如果我尝试使用字典,我会收到一个错误,即无法将字典隐式转换为任务

    private Task<Dictionary<string, string>> GetDamagedBuildings()
    {
        //Task<Dictionary<string, string>> damagedBuildings = new Task<Dictionary<string,string>>();
        Dictionary<string, string> d = new Dictionary<string, string>();
        foreach (ButtonPlanetMap i in buttonArray)
        {
            //Dictionary<string, string> d = new Dictionary<string,string>();
            if (Convert.ToInt32(i.efficiency) < 100)
            {
                d.Add(i.buildingID.ToString(), i.buildingName);
                //(Dictionary<string, string>)damagedBuildings.
            }
        }
        //damagedBuildings = Cast d;
        //return damagedBuildings;
        return d;
    }
4

3 回答 3

6

没有什么特别之处,您可以以完全相同的方式从您的方法int中返回 a 。Dictionary

你究竟应该做什么取决于你的方法为什么返回一个Task.

  1. 如果你没有充分的理由退回 a Task,不要退回 a Task,直接退回 the Dictionary
  2. 如果您要返回 aTask以实现接口,但实际上并不想让您的方法异步,那么Task.FromResult()这是一个很好的解决方案。你可以像这样使用它:return Task.FromResult(dictionary);. 这样Task还是可以await编辑的,只是await立马完成。
  3. 如果您返回 aTask因为您的方法是 CPU 密集型的,并且您想在后台线程上执行它,那么您应该使用Task.Run()

    return Task.Run(() =>
    {
        var dictionary = new Dictionary<string, string>();
        …
        return dictionary;
    });
    

    但是这样做通常不是一个好主意,请参阅我应该为同步方法公开异步包装器吗?

于 2013-06-08T13:57:30.933 回答
2

使用Task.FromResult将意味着您的方法同步运行,然后返回已完成的任务,这可能不是您想要的(尽管您可以等待已完成的任务)。

您可以使用TaskFactory.StartNew开始一个新任务。如果您使用的是 .Net 4.5,则可以使用Task.Run代替它使用TaskFactory.StartNew一些常见的默认参数。

Task<Dictionary<string,string>> GetDamaged()
{
    return Task.Factory.StartNew(() => {
        Dictionary <string, string> e = new Dictionary<string, string>();

        foreach(Building i in buildingArray)
        {
            if(Convert.ToInt32(i.efficiency) < 100)
            {
                e.Add(i.buildingID, i.buildingName);
            }
        }

        return e;
    }
}
于 2013-06-08T11:17:00.320 回答
1

当您的async方法的返回值为 时Task<int>,您的代码应返回int. 同样,当您的async方法的返回值为 时Task<Dictionary<string, string>>,您的代码应返回Dictionary<string, string>.

async Task<Dictionary<string, string>> getDamagedAsync()
{
    Dictionary<string, string> e = new Dictionary<string, string>();

    var buildingArray = await GetBuildingsAsync();
    foreach (Building i in buildingArray)
    {
        if (Convert.ToInt32(i.efficiency) < 100)
        {
            e.Add(i.buildingID, i.buildingName);
        }
    }

    return e;
}
于 2013-06-08T13:22:12.920 回答