0

I am trying to get my head around tuple for the first time using it in an async function. When testing I am not able to catch the response. I have been google the problem but not been able t solve it.

I want to run an async function that return three strings. I am not able to catch the response. Have tried referencing item or the name.

Here is the code:

var _moonAndSunResult = CleanSunAndMoonJson(_moonJson);
print(_moonAndSunResult);

Tried referencing the _moonAndSunResult in different ways.

// async Task<Tuple<string, string, string, string>> CleanSunAndMoonJson(string _json)
async Task<(string, string, string, string)> CleanSunAndMoonJson(string _json)
{

    print("sunRise: " + GetCorrectTimeFormat("sunRise", _json));
    print("sunSet: " + GetCorrectTimeFormat("sunSet", _json));
    print("moonRise: " + GetCorrectTimeFormat("moonRise", _json));
    print("moonSet: " + GetCorrectTimeFormat("moonSet", _json));

    Utility.sunrise = GetCorrectTimeFormat("sunRise", _json);
    Utility.sunset = GetCorrectTimeFormat("sunSet", _json);
    Utility.moonrise = GetCorrectTimeFormat("moonRise", _json);
    Utility.moonset = GetCorrectTimeFormat("moonSet", _json);



    await Task.Yield();

    //return (firstValue, secondValue, thirdValue);

    //return new Tuple<string, string, string, string>(Utility.sunrise, Utility.sunset, Utility.moonrise, Utility.moonset);
    return (Utility.sunrise, Utility.sunset, Utility.moonrise, Utility.moonset);
    //return Tuple.Create(Utility.sunrise, Utility.sunset, Utility.moonrise, Utility.moonset);
}

I get this from the _moonAndSunResult print above

System.Threading.Tasks.Task`1[System.ValueTuple`4[System.String,System.String,System.String,System.String]]
PeterK
  • 4,243
  • 4
  • 44
  • 74
  • 5
    You do not await the task – MakePeaceGreatAgain Sep 12 '22 at 07:31
  • There's nothing particularly tuple-specific here. If you had an async method returning `Task` it would print `System.Threading.Tasks1[System.String]`. You should await the response, at which point you'll have the tuple ready to print. – Jon Skeet Sep 12 '22 at 07:31
  • 2
    People already telling you to await the call, but there's actually nothing in your method here that requires it to be async in the first place. So just remove all of the `Task` related stuff. – DavidG Sep 12 '22 at 07:52
  • 3
    @Jodrell No, [dont use `.Result`](https://stackoverflow.com/a/47290354). Use proper async/await (if requiring async, but it's not even required). Using `.Result` [can even cause lock-ups](https://montemagno.com/c-sharp-developers-stop-calling-dot-result/). – JHBonarius Sep 12 '22 at 07:53
  • 3
    I would highly recommend naming your values, i.e. `(string Sunrise, string SunSet, string Moonrise, string Moonset)`. That way you have some chance of knowing what the properties mean. I would also consider if `string` is the correct type to use for something that sounds like a time. – JonasH Sep 12 '22 at 07:55
  • @JonasH tx the return time is formatted in a specific time so I prep that earlier and store in string. – PeterK Sep 12 '22 at 08:06
  • As a general rule, convert any strings to a real type as early as possible, and convert back to strings as late as possible, i.e. isolate any conversion code to the serialization and UI-layers. If I where calling that method, I would have to assume that ``("", "08:20", "-132", "bob")` would be a perfectly valid result. – JonasH Sep 12 '22 at 08:19
  • @JHBonarius, agreed yes but if you just need a dirty hack to see the result of a task, then `.Result` would work. Obviously, there is no point blocking with `.Result` in completed code, it defeats the point of [TAP](https://learn.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap) – Jodrell Sep 12 '22 at 09:47
  • @JHBonarius except in special cases where performance really matters and you are certain that the task is completed. https://stackoverflow.com/a/47284801/659190 – Jodrell Sep 12 '22 at 10:04
  • @Jodrell Yes, very specific cases, of course. But the OP seems to be a beginner, and one should not teach beginners bad habits. – JHBonarius Sep 12 '22 at 11:25

2 Answers2

7

What @YoungDeiza said (await the task), but really you don't need to use tasks here:

(string Sunrise, string Sunset, string Moonrise, string Moonset) CleanSunAndMoonJson(string _json)
{
    ...

    var sunrise = GetCorrectTimeFormat("sunRise", _json);
    var sunset = GetCorrectTimeFormat("sunSet", _json);
    var moonrise = GetCorrectTimeFormat("moonRise", _json);
    var moonset = GetCorrectTimeFormat("moonSet", _json);

    return (sunrise, sunset, moonrise, moonset);
}

then

var _moonAndSunResult = CleanSunAndMoonJson(_moonJson);
tymtam
  • 31,798
  • 8
  • 86
  • 126
3

You need to await the asynchronous method:

public static async Task Main()
{
    var _moonAndSunResult = await CleanSunAndMoonJson(_moonJson);
    print(_moonAndSunResult);
}

If you do not await it, you call print on a task not the result of the task.

YungDeiza
  • 3,128
  • 1
  • 7
  • 32