Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning a Task of type Task<Dictionary<string, string>>

I've been trying to figure out how to return data in type Task other than an int like this for example, Task<Dictionary<string, string>>.

All the examples I seem to find all show returning an Task<int>. which is easy enough to do by saying return 42;.

The function I've been trying to write works something like this:

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
        }
    }

I found the Task.FromResult method which looked somewhat promising, but further investigation appears to show that TResult as a completed task which to me sounds not necessarily like one that you can await.

Any ideas on how to get this working correctly?

Update

The point of this method is I am trying to offload work from my UI thread to keep my UI responsive. This is one of my first attempts at really trying to do this using visual studio 2012 with .net4.5. The code above I wrote from memory. I'll post the actual code I've been attempting along with commented out failed attempts.

One part that really bugs me is that if I return a int if my return type is task, but if I try with dictionary I get an error about cannot implicitly convert a dictionary to a task

    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;
    }
like image 434
Jazzeroki Avatar asked Feb 27 '26 20:02

Jazzeroki


2 Answers

There is nothing special about int, you can return a Dictionary from your method exactly the same way.

What exactly you should do depends on why does your method return a Task.

  1. If you don't have good reason for returning a Task, don't return a Task, return the Dictionary directly.
  2. If you're returning a Task to fulfill an interface, but you don't actually want to make your method asynchronous, Task.FromResult() is a good solution. You can use it something like this: return Task.FromResult(dictionary);. Such Task can still be awaited, it's just that the await will complete immediately.
  3. If you're returning a Task because your method is CPU intensive and you want to execute it on a background thread, then you should use Task.Run():

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

    But doing this is often not a good idea, see Should I expose asynchronous wrappers for synchronous methods?

like image 136
svick Avatar answered Mar 01 '26 10:03

svick


Using Task.FromResult will mean your method runs synchronously and then return a completed task, which is probably not what you intend (although you can await a completed task).

You can start a new task using TaskFactory.StartNew. If you are using .Net 4.5, you can use Task.Run instead which uses TaskFactory.StartNew with some common default arguments.

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;
    }
}
like image 24
Lee Avatar answered Mar 01 '26 08:03

Lee



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!