質問

Starting from an issue I had on my code, I've created this simple app to recreate the problem:

private async void button1_Click(object sender, EventArgs e)
{
    Task task = Task.Run(() =>
    {
        TestWork();
    });
    try
    {
        await task;
        MessageBox.Show("Exception uncaught!");
    }
    catch (Exception) { MessageBox.Show("Exception caught!"); }
}

private async void button2_Click(object sender, EventArgs e)
{
    Task task = TestWork();
    try
    {
        await task;
        MessageBox.Show("Exception uncaught!");
    }
    catch (Exception) { MessageBox.Show("Exception caught!"); }
}

private async Task TestWork()
{
    throw new Exception();
}

The code for button1_Click will not catch the exception. I've verified that this is because I'm not awaiting the TestWork async method. Indeed I've a warning message from Visual Studio that inform me I'm not awaiting the method. However the solution compile and I'm scared this can happen somewhere else in my code if I use extensively the async/await. So can you please explain the reason and peraphs give some golden rule to avoid it?

P.S.: It works if in the code for button1_Click I write:

Task task = Task.Run(async () =>
{
    await TestWork();
});
役に立ちましたか?

解決

In your first button1_Click implementation, you are ignoring the result of the Task returned by TestWork.

In your modified version, the await checks for an Exception and propogates it for you to catch.

In fact, the compiler warning you are seeing is normally important. If TestWork actually ran something on a different thread, then because the wrapper Task in your first implementation doesn't wait for TestWork to complete, it would just complete itself as soon as TestWork had started.

Writing it this way makes it clearer:

Task task = Task.Run( () =>
    {
        Task t = TestWork();
        // ignore t
    }
);
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top