简体   繁体   中英

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?

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();
}

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM