ChatGPT解决这个技术问题 Extra ChatGPT

How does Task<int> become an int?

We have this method:

async Task<int> AccessTheWebAsync()
{ 
    HttpClient client = new HttpClient();

   Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");

   // You can do work here that doesn't rely on the string from GetStringAsync.
   DoIndependentWork();

   string urlContents = await getStringTask;
   //The thing is that this returns an int to a method that has a return type of Task<int>
   return urlContents.Length;
}

Does an implicit conversion occur between Task<int> and int? If not, then what is happening? How is it implemented to work?

Keep reading. I assume the compiler takes care of that based on the async keyword.
@Freeman, Look at this great explanation: stackoverflow.com/a/4047607/280758

k
kmad1729

Does an implicit conversion occur between Task<> and int?

Nope. This is just part of how async/await works.

Any method declared as async has to have a return type of:

void (avoid if possible)

Task (no result beyond notification of completion/failure)

Task (for a logical result of type T in an async manner)

The compiler does all the appropriate wrapping. The point is that you're asynchronously returning urlContents.Length - you can't make the method just return int, as the actual method will return when it hits the first await expression which hasn't already completed. So instead, it returns a Task<int> which will complete when the async method itself completes.

Note that await does the opposite - it unwraps a Task<T> to a T value, which is how this line works:

string urlContents = await getStringTask;

... but of course it unwraps it asynchronously, whereas just using Result would block until the task had completed. (await can unwrap other types which implement the awaitable pattern, but Task<T> is the one you're likely to use most often.)

This dual wrapping/unwrapping is what allows async to be so composable. For example, I could write another async method which calls yours and doubles the result:

public async Task<int> AccessTheWebAndDoubleAsync()
{
    var task = AccessTheWebAsync();
    int result = await task;
    return result * 2;
}

(Or simply return await AccessTheWebAsync() * 2; of course.)


can any details be offered for how it works under the hood, just curious.
+1 Good answer as always. And why are you so pretty fast writing them?!
+1: Just started looking into async/await and I find this extremely non-intuitive. IMO, there should be a keyword or similar at the return to make this clear, e.g. return async result; (in the same way that await result "unwraps" the T from the Tast<T>).
@JonSkeet But it doesn't make sense without the await - with T foo = someTaskT; you'd get "Cannot implicitly convert type Task<T> to T" - in the same way I argue that it would make more sense to have a keyword for the inverse (wrapping in Task<T>). I'm all for removing fluff but in this case I think it provides an unnecessary obfuscation within async methods. (Obviously the point is moot because the powers that be have already spoken/coded!)
@dav_i: The assignment doesn't make sense, but the rest does. And there are cases where the whole statement would make sense - although it might not be useful. Given that the method is already declared async, I think that's enough.
F
Fábio Nascimento

No requires converting the Task to int. Simply Use The Task Result.

int taskResult = AccessTheWebAndDouble().Result;

public async Task<int> AccessTheWebAndDouble()
{
    int task = AccessTheWeb();
    return task;
}

It will return the value if available otherwise it return 0.


that is not what i asked.
This does not answer the question. But more importantly, this is very bad advice. You should almost never use Result; it can cause deadlocks! Consider for example this workflow: (1) Write a note that says "mow the lawn". (2) Wait for the lawn to be mowed (3) Eat a sandwich, (4) Do whatever it says on the note". With that workflow, you never eat a sandwich or mow the lawn, because step 2 is a synchronous wait on something that you will do in the future. But that's the workflow that you are describing here.
@EricLippert: Not clear your example. Can you please explain how Result can introduce deadlocks when await won't?
Await means to do something while you're waiting for the result and that something can include doing work to compute the result. But synchronous waits do nothing while you wait which means you could be preventing the work from being done.
@EricLippert. Will this have the same issue ? 'Task.Run(()=> AccessTheWebAndDouble()).Result;'