Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to run async lambda synchronously?

Is there a way to run async lambda synchronously? It is not allowed to modify lambda expression, it must be leaved as is.

Copy/paste example(it's an abstraction):

var loopCnt = 1000000;

Action<List<int>> aslambda = async (l) =>
{
    Thread.Sleep(100);
    await Task.Run(() => { });
    for (int i = 0; i < loopCnt; i++) { l.Add(i); }
};

var lst = new List<int>();
aslambda(lst); //This runs asynchronously 
if (lst.Count < loopCnt-100) { ; }

Solution:

It is really a dilemma for me to accept one answer. I have tried out the solution from Stephen Cleary with NuGet package - works brilliant and is broad applicable, but an answer from dvorn to the question(as it's formulated ;)) is much easier.

Has dvorn changed the signature of lambda? No and Yes ;)

From MSDN:

Note that lambda expressions in themselves do not have a type because the common type system has no intrinsic concept of "lambda expression." However, it is sometimes convenient to speak informally of the "type" of a lambda expression. In these cases the type refers to the delegate type or Expression type to which the lambda expression is converted.

So both receive +1 and accepted answer by Stephen Cleary

like image 461
Rekshino Avatar asked Apr 12 '17 12:04

Rekshino


People also ask

Is it possible to make a Lambda that executes asynchronously?

Lambda functions can be invoked either synchronously or asynchronously, depending upon the trigger. In synchronous invocations, the caller waits for the function to complete execution and the function can return a value.

How do you make AWS Lambda synchronous?

To invoke a function synchronously with the AWS CLI, use the invoke command. The cli-binary-format option is required if you're using AWS CLI version 2. To make this the default setting, run aws configure set cli-binary-format raw-in-base64-out . For more information, see AWS CLI supported global command line options.

Can Lambda call another Lambda asynchronously?

Async lambda invocation is the simplest and straightforward way to go about this problem. Async invocation means that the lambda that invokes the other lambda does not wait for the second lambda to finish and immediately returns.


2 Answers

Is there a way to run async [void] lambda synchronously?

Yes, but like all sync-over-async hacks, it's dangerous and won't work for all lambdas.

You must have a custom SynchronizationContext to detect the completion of an async void method (or lambda). This is non-trivial, but you can use my AsyncContext (available in the NuGet package Nito.AsyncEx.Context):

AsyncContext.Run(() => aslambda(lst));
like image 95
Stephen Cleary Avatar answered Oct 02 '22 21:10

Stephen Cleary


Better solution: You cannot change the lambda, but you may change the type of local variable it is assigned to. Note that native type of async lambda is not Action but Func<Task>.

...
Func<List<int>, Task> aslambda = async (l) =>
...
...
aslambda(lst).Wait();
...
like image 20
dvorn Avatar answered Oct 02 '22 22:10

dvorn