How to Write an Async Method with Out Parameter

How to write an async method with out parameter?

You can't have async methods with ref or out parameters.

Lucian Wischik explains why this is not possible on this MSDN thread: http://social.msdn.microsoft.com/Forums/en-US/d2f48a52-e35a-4948-844d-828a1a6deb74/why-async-methods-cannot-have-ref-or-out-parameters

As for why async methods don't support out-by-reference parameters?
(or ref parameters?) That's a limitation of the CLR. We chose to
implement async methods in a similar way to iterator methods -- i.e.
through the compiler transforming the method into a
state-machine-object. The CLR has no safe way to store the address of
an "out parameter" or "reference parameter" as a field of an object.
The only way to have supported out-by-reference parameters would be if
the async feature were done by a low-level CLR rewrite instead of a
compiler-rewrite. We examined that approach, and it had a lot going
for it, but it would ultimately have been so costly that it'd never
have happened.

A typical workaround for this situation is to have the async method return a Tuple instead.
You could re-write your method as such:

public async Task Method1()
{
var tuple = await GetDataTaskAsync();
int op = tuple.Item1;
int result = tuple.Item2;
}

public async Task<Tuple<int, int>> GetDataTaskAsync()
{
//...
return new Tuple<int, int>(1, 2);
}

How to use async await with out parameter in c#

In short, you don't (and you can't), we use a return

Also, when you think about it, it doesn't make any sense, its a task that finishes when it likes, if you could do that you would be forcing it to wait for the out parameter

public async Task<SomeResult> someOtherMethod() { .. }

...

var myAwesomeResult = await someOtherMethod();

Also, you cold use a delegate, func<T,U> or Action<T> as a parameter

public async Task someOtherMethod(Action<bool> someResult)
{
await somestuff;
someResult(true);
}

...

await someOtherMethod(b => YayDoSomethingElse(b));

Ooor as Daniel A. White commented, you could return a ValueTuple if you need easy access to multiple return types

public async Task<(int someValue,string someOtherValue)> someOtherMethod() {.. }

ref and out arguments in async method

Does anyone know why async methods are not allowed to have ref and out arguments?

Sure. Think about it - an async method usually returns almost immediately, long before most of the actual logic is executed... that's done asynchronously. So any out parameters would have to be assigned before the first await expression, and there'd quite possibly have to be some restriction on ref parameters to stop them from being used after the first await expression anyway, as after that they may not even be valid.

Consider calling an async method with out and ref parameters, using local variables for the arguments:

int x;
int y = 10;
FooAsync(out x, ref y);

After FooAsync returns, the method itself could return - so those local variables would no longer logically exist... but the async method would still effectively be able to use them in its continuations. Big problems. The compiler could create a new class to capture the variable in the same way that it does for lambda expressions, but that would cause other issues... aside from anything else, you could have a local variable changing at arbitrary points through a method, when continuations run on a different thread. Odd to say the least.

Basically, it doesn't make sense to use out and ref parameters for async methods, due to the timing involved. Use a return type which includes all of the data you're interested in instead.

If you're only interested in the out and ref parameters changing before the first await expression, you can always split the method in two:

public Task<string> FooAsync(out int x, ref int y)
{
// Assign a value to x here, maybe change y
return FooAsyncImpl(x, y);
}

private async Task<string> FooAsyncImpl(int x, int y) // Not ref or out!
{
}

EDIT: It would be feasible to have out parameters using Task<T> and assign the value directly within the method just like return values. It would be a bit odd though, and it wouldn't work for ref parameters.

Azure Function : async method and output parameters

You are looking for IAsyncCollector<T> to change from out param to that. Instead of “out string message” you change to ICollector<string> messages or IAsyncCollector<string> and add you message to the collection in the body.

Passing Task as parameter to be invoked within loop in async method C#

You are passing the result of calling Print1() to the method (a Task). You aren't passing the method itself. So it's only called once at Print1(). When you await printer;, it's really just saying "yup, it happened" and moving on.

If you want to pass the method itself, so that it can be called inside PrintLoop, then you need to accept a Func<Task> (a method that returns a Task).

Then you pass the method itself (Print1) without calling it (not Print1())

async Task Main()
{
await PrintLoop(Print1); //not Print1()
}

async Task Print1()
{
Debug.WriteLine("Printing!");
}

async Task PrintLoop(Func<Task> printer, int iterations = 3)
{
for (int i = 0; i < iterations; i++)
{
await printer();
}
}


Related Topics



Leave a reply



Submit