C# - 从异步方法

时间:2018-04-19 10:21:50

标签: c# async-await

我有在button_click里面调用的Async方法。异步方法运行3个不同的void,每个void都有自己的错误处理。如果在这3个方法中出现任何错误,我想在button_click中显示该特定错误消息和停止代码 - 这也运行更多非异步方法并且具有错误处理功能。我做的是这个(例子):

private void button1_Click(object sender, EventArgs e)
{
    try
    {
       //calling non-async method, if It fails It should show error 
       //inside this event
       Method1();

        if (TestAsync().IsCanceled)
        {
            return;
        }

        MessageBox.Show("Test");
    }
    catch (Exception)
    {
        MessageBox.Show("Async method failed and this message should not be diplayed!");
        throw;
    }
}

public async Task<bool> TestAsync()
{
    bool completed = await Task.Run(() => MethodToComplete());
    return completed;
}

private bool MethodToComplete()
{
    try
    {
        //renaming file, but intentionally fail for test purpose
        Directory.Move("fail_this_method", "fail");
        return true;
    }
    catch (Exception ex)
    {
        MessageBox.Show("Error: " + ex.Message);
        return true;
        throw;
    }
}

此示例的结果是 - 它显示来自void的错误消息,该消息是异步调用的,并且不会显示来自button_click的错误消息。但是它还显示 MessageBox.Show(&#34; Test&#34;); ,如果异步失败,则button_click中的代码应立即停止。

我希望我足够清楚,任何有用的帮助!

1 个答案:

答案 0 :(得分:0)

在async-await之前还有其他任务处理方法,如Task.ContinueWithTask.IsCanceled等。

如果您打算使用async-await,请不要将它们与这些旧功能混合使用。坚持以下规则:

  • 如果等待对另一个异步函数的调用
  • ,则仅声明函数async
  • 每个异步函数都应该返回Task<TResult>而不是TResultTask而不是Task
  • 有一个例外:异步事件处理程序返回void

此外:

  • 如果您调用异步函数,但不需要立即执行结果,请考虑不要等待,但执行其他操作。只在需要async函数的结果时才等待
  • 等待后继续的线程可能是一个不同的线程。但是具有相同的上下文。这样做可以使您将其视为原始线程。不需要InvokeRequired,锁和互斥锁
  • 如果您不需要相同的上下文,请在等待之后考虑`CongigureAwait(false)。这将加快该过程,但缺点是持续的线程可能无法访问您的表单控件。

记住这一点,您的代码可以如下:

private async void button1_Click(object sender, EventArgs e)
{
    // this function must be async because if awaits
    // it is an event hander, hence it returns void instead of Task
    try
    {
        Method1();

        // call TestAsync, if you do not need the result right now,
        // do not await yet
        var myTask = TestAsync();

        // as soon as TestAsync has to await, it continues here:
        // results from TestAsync are not available yet
        DoSomeOtherProcessing();

        // now you need the result from testAsync; await the Task
        bool result = await myTask;
        ProcessResult(result);
    }
    catch (Exception)
    {
       ...
    }
}

取消的Task应该抛出TaskCanceledException。你不应该检查MyTask.IsCanceled,但要抓住这个例外。

帮助我理解async-await的文章

  • T his interview with Eric Lippert在中间某处搜索async-await。埃里克将async-await与做饭的厨师比较。一旦他戴上水壶,他就不会懒得等待水沸腾,而是环顾四周,看看他是否可以做其他事情,比如切洋葱
  • async-await由有用的Stephen Cleary提供