Tom Pažourek
Tom Pažourek

Reputation: 10167

Windows form breaks when calling Task.Result

I have code similar to following inside my Windows form:

private async Task<string> GetGreetingAsync()
{
    return await Task.Run(() => "Hello");
}

private void button1_Click(object sender, EventArgs e)
{
    var x = GetGreetingAsync().Result;
}

Clicking the button causes the entire Windows form to freeze and become unresponsive. No exception is thrown.

Even when I don't use the task .Result directly in the event handler and the whole async marked code is in some class library function, which provides interface without async, the problem still occurs. Unit tests for such class library pass without any problems, but when I call its function from event handler on Windows form, it breaks and does not respond.

Why does this happen? How can I fix it?

Upvotes: 3

Views: 1642

Answers (2)

L.B
L.B

Reputation: 116108

You are blocking the the UI thread with .Result; (see ConfigureAwait)

private async Task<string> GetGreetingAsync()
{
    return await Task.Run(() => "Hello").ConfigureAwait(false);
}

private void button1_Click(object sender, EventArgs e)
{
    var x = GetGreetingAsync().Result;
}

Or go all the way async

private async Task<string> GetGreetingAsync()
{
    return await Task.Run(() => "Hello");
}

async private void button1_Click(object sender, EventArgs e)
{
    var x = await GetGreetingAsync();
}

Using this version you don't even need to await in GetGreetingAsync

private Task<string> GetGreetingAsync()
{
    return Task.Run(() => "Hello");
}

async private void button1_Click(object sender, EventArgs e)
{
    var x = await GetGreetingAsync();
}

Upvotes: 10

msarchet
msarchet

Reputation: 15242

You should be using await instead of Result on a Task<T> to get non-blocking behavior.

private async void button1_Click(object sender, EventArgs e)
{
    var x = await GetGreetingAsync();
}

Calling Result causes the code to wait until the Task has completed where calling await allows the async behavior to be used.

Edit

Actually looking at your code again if you're doing

private async Task<string> GetGreetingAsync()
{
  return await new Task<string>(() => "Hello");
}

That is really not needed. That block can just be

private Task<string> GetGreetingAsync()
{
  return new Task<string>(() => "Hello");
}

There's no need for the thing returning the task to be async.

Upvotes: 0

Related Questions