简体   繁体   English

C#-从异步方法返回布尔值

[英]C# - return boolean from Async method

I have Async method which is called inside button_click. 我有在button_click内部调用的Async方法。 Async method runs 3 different void's and each void has It's own error handling. 异步方法运行3个不同的void,每个void具有自身的错误处理。 If any error inside those 3 methods occure I want to show that particular error message and stop code inside button_click - which also runs more non-async method and has It's error handling. 如果在这3种方法中发生任何错误,我想显示特定的错误消息并在button_click中停止代码-该方法也运行更多的非异步方法并具有错误处理功能。 What I did was this (example): 我所做的就是这个(示例):

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

The result of this example is - It does display error message from void which is called asynchronously and doesn't show error message from button_click. 该示例的结果是-它确实显示来自void的错误消息,该消息被异步调用,并且不显示来自button_click的错误消息。 But It also displays MessageBox.Show("Test"); 但是它还会显示MessageBox.Show(“ Test”); which shouldn't, code in button_click should stop immidiately if Async fails. 不应该这样,如果异步失败,button_click中的代码应立即停止。

I hope I was clear enough, any help kindly appreaciated ! 我希望我已经足够清楚,请给予任何帮助!

Before async-await there were other task handling methods, like Task.ContinueWith , Task.IsCanceled etc. 在异步等待之前,还有其他任务处理方法,例如Task.ContinueWithTask.IsCanceled等。

If you plan to use async-await, don't mix them with these older functions. 如果您打算使用异步等待,请不要将它们与这些较早的功能混合使用。

When you decide to use async-await, stick to the following rules: 当您决定使用async-await时,请遵循以下规则:

  • only declare a function async if it awaits a call to another async function 仅在等待另一个异步函数的调用时声明一个异步函数
  • every async function should return Task<TResult> instead of TResult and Task instead of void 每个异步函数都应返回Task<TResult>而不是TResultTask而不是void
  • There is one exception: an async event handler returns void 有一个例外:异步事件处理程序返回void

Furthermore: 此外:

  • If you call an async function, but you do not need the result immediately, consider not to await yet, but do the other things. 如果调用异步函数,但是您不立即需要结果,请考虑不要等待,而是执行其他操作。 Start awaiting when you need the results of the async function 需要异步功能的结果时开始等待
  • After the await the thread that continues may be a different thread. 等待之后,继续的线程可能是另一个线程。 But it has the same context . 但是它具有相同的上下文 This has the effect that you can regard this as if it is the original thread. 这样的效果是,您可以将其视为原始线程。 No need for InvokeRequired , locks and mutexes 不需要InvokeRequired ,锁和互斥锁
  • If you don't need the same context, consider ConfigureAwait(false) after the await. 如果不需要相同的上下文,请在等待之后考虑ConfigureAwait(false) This will speed up the process, with the disadvantage that the continuing thread does not have the user interface context. 这将加快处理速度,其缺点是连续线程不具有用户界面上下文。 Therefore you can't access windows Form controls. 因此,您无法访问Windows Form控件。

Keeping this in mind, you code could be as follows: 请记住,您的代码可能如下所示:

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)
    {
       ...
    }
}

A Task that is cancelled, should throw TaskCanceledException . 被取消的Task应该抛出TaskCanceledException You should not check MyTask.IsCanceled , but catch this exception. 您不应检查MyTask.IsCanceled ,但应捕获此异常。

Articles that helped me understanding async-await 有助于我理解异步等待的文章

  • T his interview with Eric Lippert Search somewhere in the middle for async-await. 在中间某个地方接受Eric Lippert Search的采访,以进行异步等待。 Eric compares async-await with a cook making dinner. 埃里克将异步等待与做饭的厨师进行比较。 Once he put on the kettle, he does not idly wait for the water to boil, but looks around to see if he can do other things instead, like chopping onions 一旦放上水壶,他就不会闲着等待水烧开,而是四处看看是否可以做其他事情,例如切碎洋葱。
  • async-await by the ever so helpful Stephen Cleary 非常有帮助的Stephen Cleary 异步等待

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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