Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async / Await Lambdas

I have a strange problem combining the async/await to make it work: I created a small procedure, which should handle basically the 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);
        }

Nohing to fancy, but it's worth since changing error-handling is very easy made. But what happens, if I'd like to get Data async in the Lambda? Lets take this simple example:

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

Sure, the HandledAction gets called, passes, since it gets the pointer back, and the exception gets thrown, of course not handled.

I imagine I have to create a AsyncHandledAction, and set the action async, but is there a easier way to solve this problem?

I guess many people use a central exception-handling, and there are far better solutions for this?

Thanks in advance

Matthias

Edit: I created an example, which should shpw netter I need: I basically dont want the whole Action I pass being awaitable, but one call in the Lambda is:

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

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

Error 3 The 'await' operator can only be used within an async lambda expression. Consider marking this lambda expression with the 'async' modifier.

like image 461
Matthias Müller Avatar asked Oct 14 '25 08:10

Matthias Müller


1 Answers

The reason is: Action instead of Func. Since yours:

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

in fact is:

async void Method() { }

when Func<Task> is:

async Task Method() { }

Async void will capture SynchronizationContext.Current and when exception is thrown it will be posted to SynchronizationContext by SynchronizationContext.Post() - (in windows runtime you can catch these types of exception). In case of ASP.NET/Console application SynchronizationContext.Current returns null which means that exception would be propagated to Thread Pool and I'm not sure but I think it is not possible to catch it. However when there is returned Task by asynchronous method exception could be marshaled to the caller through this returned Task. It is also worth mention that async lambda expresions will always prefer methods with Func<Task> over Action. General rule is: never use async void (async Action) unless it is "top-level method" (in example event handler).

like image 197
fex Avatar answered Oct 16 '25 21:10

fex



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!