3

I just had following piece of code, which did not compile:

public Task<int> Handle
{
    var result = <do_something_returning_an_int>();
    ...
    return result;
}

This gives compiler error `cannot implicitly convert type 'int' to 'System.Threading.Thread.Task'.

When I change this into:

async Task<int> Handle
{
    var result = <do_something_returning_an_int>();
    ...
    return result;
}

... no compiler error.

I know that async means that the task does not need to wait for the answer to arrive, but what does this have to do with typecasting?

Dominique
  • 16,450
  • 15
  • 56
  • 112
  • 6
    Is the method using an `await` anywhere? If the method isn't `async` then it won't automatically produce a `Task<>`, the code would need to return that type explicitly. And an `int` is not a `Task`. (The difference between those types has exactly nothing to do with the `public` access modifier.) – David Nov 23 '22 at 16:04
  • 2
    I would suggest to make both methods `public`, to eliminate any confusion regarding this difference. – Theodor Zoulias Nov 23 '22 at 16:06
  • 1
    `async` actually means: this method has something that can be `await`ed. Otherwise there's no need to use `async`. – MakePeaceGreatAgain Nov 23 '22 at 16:13
  • This is a part of the C# Language Specification. Read it, or read [Async return types (C#) § `Task` return type](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/async-return-types#tasktresult-return-type). – Jeppe Stig Nielsen Nov 23 '22 at 16:38
  • @JeppeStigNielsen: your comment seems to be the closest to the solution. Can you put it as an answer? I'll accept it. – Dominique Nov 24 '22 at 07:29

3 Answers3

5

If you're not awaiting anything in your asynchronous method you omit the async keyword and return a Task instead of the result directly.

public Task<int> Handle
{
    var result = <do_something_returning_an_int>();
    ...
    return Task.FromResult(result);
}

As far as I can tell, doing that only makes sense if other code strictly expects a Task from your method.

This has of course nothing to do with access modifiers, you can combine async with public or any other access modifier.

I'd also recommend taking a look at the documentation

noel
  • 531
  • 2
  • 7
2

(By request, promoted from a comment.)

This is by design of the async logic in the C# Language Specification. See the section Async Functions.

You can also read the programming guide, Async return types (C#) § Task<TResult>.

The point is that a method without the async keyword, like

public Task<int> HandleAsync()
{
    ...
    Task<int> result = ...;
    ...
    return result;
}

must return what it says it returns, just as with all other types. In this case, you could create a Task<> that can be awaited, in your own manual way, like:

Task<int> result = Task.Run(GetLastDigitOfSmallestTwinPrimeWithMoreThan1000000Digits);

The caller can await the task you return, even if your method is written like above.

But if you use the async keyword, and if your return type is, say, Task<int>, then you must return a plain int, and the C# compiler will write the needed logic for you.

Usually, you would use await somewhere in the body (otherwise, why async). So something like:

public async Task<int> HandleAsync()
{
    ...
    int result = await GetLastDigitOfSmallestTwinPrimeWithMoreThan1000000DigitsAsync();
    ...
    return result;
}

Related question here: Why is it not necessary to return a Task when the signature is public async Task MethodName?

Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
1

try using task result and then iterate the results

Task<int> Handle
{
    return Task.Run(()=>
    {
       var result = <do_something_returning_an_int>();
       ...
       return result;
    }
}

List<Task<int>> tasks = new List<Task<int>>();
tasks.Add(Handle);
Task.WaitAll(tasks.ToArray());
for(int ctr = 0; ctr < tasks.Count; ctr++) {
                if (tasks[ctr].Status == TaskStatus.Faulted)
                    output.WriteLine(" Task fault occurred");
                else
                {
                    output.WriteLine("test sent {0}",
                                      tasks[ctr].Result);
                    Assert.True(true);
                }
            }

or

Task<int> Handle
{
   return Task.FromResult(do_something_returning_an_int);
}
Golden Lion
  • 3,840
  • 2
  • 26
  • 35