Async / Await Lambdas

I have a weird problem combining async / await to make it work: I created a little routine that should handle basically try / catch of every action:

    internal static void HandledAction(Action action, Info infoBar)
    {
        try
        {
            action();
        }
        catch (Exception ex)
        {
            infoBar.SetError("An Exception occured: " + ex.Message);
            WriteLog(ex.StackTrace);
        }

      

It takes some imagination, but it's worth it that changing the error handling is very easy. But what happens if I want to receive async data in Lambda? Let's take a look at this simple example:

    private void mnuImportData_Click(object sender, RoutedEventArgs e)
    {
        ActionHelper.HandledAction(async () =>
        {
            throw new NotImplementedException("Ups");
        }, infoMain);
    }

      

Of course, HandledAction gets called passes because it returns a pointer back and the exception gets, of course, is not handled.

I am assuming I need to create an AsyncHandledAction and set an async action, but is there an easier way to solve this problem?

I think a lot of people use central exception handling and there are much better solutions for that?

Thank you in advance

Matthias

Edit: I created an example that was supposed to contain shpw netter: I basically don't want all the action I pass to be expected, but one call in the lambda:

ActionHelper.HandledActionAsync(() =>
        {
            //elided
            CheckFileResult rslt = await excelImport.CheckFilesAsync(tmpPath);
            //elided
        }, infoMain);

      

Of course, by doing this, I get the error:

Error 3 The "wait" operator can only be used in an async lambda expression. Consider marking this lambda expression with the async modifier.

+3


source to share


2 answers


You need an asynchronous version of HandleAction

internal static async Task HandledAction(Func<Task> action, Info infoBar)
{
    try
    {
        await action();
    }
    catch (Exception ex)
    {
        infoBar.SetError("An Exception occured: " + ex.Message);
        WriteLog(ex.StackTrace);
    }
}

      



of course you must call the method with an expectation

private async void mnuImportData_Click(object sender, RoutedEventArgs e)
{
    await ActionHelper.HandledAction(async () =>
    {
        throw new NotImplementedException("Ups");
    }, infoMain);
}

      

+2


source


Reason: Action instead of Func . Since your:

async () =>
        {
            throw new NotImplementedException("Ups");
        }

      

in fact:

async void Method() { }

      



when Func<Task>

:

async Task Method() { }

      

Async void will catch SynchronizationContext.Current

, and when an exception is thrown, it will be posted SynchronizationContext

on SynchronizationContext.Post()

- (at Windows runtime, you can catch these types of exceptions). In case it ASP.NET/Console application

SynchronizationContext.Current

returns null, which means the exception will be propagated to the thread pool and I'm not sure, but I think it cannot be caught. However, when returning Task

in an asynchronous method, an exception can be tied to the caller through this returned task. It's also worth mentioning that async lambda expressions will always prefer Func<Task>

over methods Action

. General rule of thumb: never use async void

( async Action

) unless it is a "top-level method" (in the example, an event handler).

+5


source







All Articles