First, i hope the title is okay.
I have a Grpc Client with the well known greeter service and try to encapsulate the SayHelloAsync call in a Func.
But the => operator is redlined because he can not convert the expression he say.
It works if i remove any async/await.
Its probably because SayHelloAsync returns AsyncUnaryCall(which have an awaiter) instead of Task but at the end its
not a Grpc issue i guess, its just my missunderstanding.
Here is my try:
static async Task Main()
{
var client = CreateGreeterClient();
await UnsafeTask<Service.HelloReply>(async () =>
{
var result = await client.SayHelloAsync(new Service.HelloRequest { Name = greeter.Name });
return Task<Service.HelloReply>.FromResult(result);
});
Console.ReadKey();
}
static async Task<T> UnsafeTask<T>(Func<AsyncUnaryCall<T>> method) where T:class
{
try
{
return await method();
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
return null;
}
}
Any tip would be greatful.
Related
I have created an API project using .NET 6.0.
I have configured the app.MapGet method correctly, and they are executing their respective methods.
These methods execute their respective Datacalls and return "Results.Ok(results)"
public static class ResultSetBeingReturned
{
public static async Task<IResult> ExecuteResultSet<T>(this Task<IEnumerable<T>> task)
{
try
{
var results = await task;
if (results == null) return Results.NotFound();
return Results.Ok(results);
}
catch (Exception ex)
{
return Results.Problem(ex.Message);
}
}
}
I want to unit test this method, so my question is: How do I invoke an API that is going to generate an Exception that is NOT a 404 Not Found?
By using an IEnumerable<T> which throws an exception in your tests:
public static async Task Main()
{
var enumerable = Task.Run(() => Error());
var res = await enumerable.ExecuteResultSet();
Console.WriteLine(res.GetType().Name); // whatever Result.Problem returns
}
private static IEnumerable<string> Error()
{
throw new Exception();
}
Live example: https://dotnetfiddle.net/FDT8fs
Another option is simply to use Task.FromException
public static async Task Main()
{
var res = await Task.FromException<IEnumerable<string>>(new Exception()).ExecuteResultSet();
Console.WriteLine(res.GetType().Name);
}
Live example: https://dotnetfiddle.net/oezJwI
I've made a queue, which contains tasks to do. After creating some tasks manually with new Task() in Returns method, my whole application hangs - await current;. The body of the task is not even triggered.
ConfigureAwait(false) didn't help.
The first task in the queue, which is not created by me, but other framework is executing successfully and returning a value. Mine - doesn't. I've tried add Task.CompletedTask and then it has worked. I don't understand why I can't even reach the body of the task containing _output assignment.
IDE debugger code screenshot
---UPDATE---
The code works when I use code below. With await it doesn't. Any ideas?
current.Start();
current.Wait();
Original code
private readonly Queue<Task> _pipe;
public IPipeBuilder<TOutput> Returns(Func<IEnumerable<IExecutionResult>, TOutput> outputBuilder)
{
_pipe.Enqueue(new Task(() => // this task causes a problem and breakpoint isn't hit inside
{
_output = outputBuilder(_results);
}));
return this;
}
public async Task<TOutput> Execute()
{
Task current;
while (_pipe.TryDequeue(out current))
{
if (current.IsCommandExecution())
{
IExecutionResult result = await (Task<IExecutionResult>)current; // this awaits successfully
_results.Add(result);
}
else
{
await current; // hangs here
}
}
return await Task.FromResult(_output);
}
Usage
[HttpGet("eventflow/pipe/issue/add/{title}")]
public async Task<IActionResult> PipeAction(string title)
=> Ok(
await Pipe<IExecutionResult>()
.Validate(title)
.Handle<AddIssueCommand>(IssueId.New, title)
.Returns(results => results.First())
.Execute());
You should never use the Task constructor. This goes double on ASP.NET, since constructed tasks are always Delegate Tasks, which interfere with the ASP.NET usage of the thread pool. The actual reason that the await hangs is because manually-created tasks need to be started.
If you have synchronous work that you need to wrap into a Task to work alongside asynchronous tasks, then you should use Task.CompletedTask and Task.FromException:
private static Task SynchronousWork(Func<IEnumerable<IExecutionResult>, TOutput> outputBuilder)
{
try { _output = outputBuilder(_results); return Task.CompletedTask; }
catch (Exception ex) { return Task.FromException(ex); }
}
public IPipeBuilder<TOutput> Returns(Func<IEnumerable<IExecutionResult>, TOutput> outputBuilder)
{
_pipe.Enqueue(SynchronousWork(outputBuilder));
return this;
}
However, note that this executes outputBuilder immediately, which may not be desirable due to its side effects on _results and _output. If you want a delayed execution queue, then the type in the queue needs to be changed from Task to Func<Task>. Then you can add to it as such:
public IPipeBuilder<TOutput> Returns(Func<IEnumerable<IExecutionResult>, TOutput> outputBuilder)
{
_pipe.Enqueue(() =>
{
try { _output = outputBuilder(_results); return Task.CompletedTask; }
catch (Exception ex) { return Task.FromException(ex); }
});
return this;
}
and you would consume it by calling each delegate one at a time and inspecting the task it returns:
public async Task<TOutput> Execute()
{
while (_pipe.TryDequeue(out var currentFunc))
{
var currentTask = currentFunc();
if (currentTask.IsCommandExecution())
{
IExecutionResult result = await (Task<IExecutionResult>)currentTask;
_results.Add(result);
}
else
{
await currentTask;
}
}
return _output;
}
Okay, thank you. I've ended up with such class and Queue<Func<Task>> like you said.
public sealed class SyncTaskWrapper
{
private Func<Task> _action;
public SyncTaskWrapper(Action action)
=> _action = CreateFunc(action);
private static Func<Task> CreateFunc(Action action)
=> () =>
{
try
{
action();
return Task.CompletedTask;
}
catch (Exception exception)
{
return Task.FromException(exception);
}
};
public static implicit operator Func<Task>(SyncTaskWrapper #this)
=> #this._action;
}
with usage
_pipe.Enqueue(new SyncTaskWrapper(() =>
_output = outputBuilder(_results)));
I am trying to create the async task for the already existing code in my project for the database connection using EF 6.
I have created async task and it works fine, you can refer Using Async Task section for the code. But I want to rewrite The existing code of the project section as async task to maintain the consistency in the project.
Using Async Task: The below code works fine.
public static async Task<Student> InsertAsync(Student student)
{
try
{
using(PracticeContext context = new PracticeContext())
{
Repository<Student> repository = new Repository<Student>(context);
return await repository.InsertAsync(student);
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
return null;
}
}
The existing code of the project:
I want to implement the below code as async task for both the Insert() and Execute() methods. So, that the data will be added to the database without holding the UI for the long time and make the project more user friendly.
Please suggest or provide the async implementation of the below codes.
public static Student Insert(Student student)
{
try
{
return Execute<Student, Student>((repository) => {
return repository.Insert(student);
});
}
catch (Exception ex)
{
Console.WriteLine(ex);
return null;
}
}
private static TResult Execute<TResult, T>(Func<Repository<T>, TResult> func) where T: class
{
using(PracticeContext context = new PracticeContext())
{
try
{
return func(new Repository<T>(context));
}
catch(Exception ex)
{
Console.WriteLine(ex);
throw new Exception("Error Occured.");
}
}
}
I would be glad to add more stuffs if required to make the questions more accurate and understandable.
The first thing you do is change the lowest-level call to use the asynchronous version and use async in its enclosing method/lambda. Then let the async grow from there. So the first step would be:
return Execute<Student, Student>(async (repository) => {
return await repository.Insert(student);
});
This code then requires Execute to allow asynchronous delegates. At this step, we probably want other code to continue using the synchronous Execute, so we can copy/paste it and make the new overload take an asynchronous delegate:
private static async Task<TResult> Execute<TResult, T>(Func<Repository<T>, Task<TResult>> func) where T: class
{
using(PracticeContext context = new PracticeContext())
{
try
{
return await func(new Repository<T>(context));
}
catch(Exception ex)
{
Console.WriteLine(ex);
throw new Exception("Error Occured.");
}
}
}
Now that the asynchronous Execute returns a Task<T>, we then need to await it back in the calling method:
return await Execute<Student, Student>(async (repository) => {
return await repository.Insert(student);
});
which then makes the calling method asynchronous as well:
public static async Task<Student> InsertAsync(Student student)
{
try
{
return await Execute<Student, Student>(async (repository) => {
return await repository.Insert(student);
});
}
catch (Exception ex)
{
Console.WriteLine(ex);
return null;
}
}
I have an async method, say:
public async Task<T> GetAsync()
{
}
and would be called from:
public async Task<IEnumerable<T>> GetAllAsync()
{
foreach (var item in something)
{
var result = await GetAsync();
yield return result;
}
}
The above syntax is not valid but basically I am after asynchronous generators. I know it can be handled via Observables. I did experiment with Rx.NET and it worked to some extent. But I am trying to avoid the complexity it brings to codebase, and more importantly the above requirement is still essentially not a reactive system (ours is still pull based). For e.g. I would only listen to the incoming async streams for a certain time and I have to stop the producer (not just unsubscribe the consumer) from the consumer side.
I can invert the method signature like this:
public IEnumerable<Task<T>> GetAllAsync()
But this makes doing LINQ operations bit tricky without blocking. I want it to be non-blocking as well as without loading the entire thing into memory. This library: AsyncEnumerable does exactly what I am looking for but how can the same be done with Ix.NET? They are meant for the same thing I believe.
In other words, how can I make use of Ix.NET to generate an IAsyncEnumerable when dealing with await? Like,
public async IAsyncEnumerable GetAllAsync()
{
foreach (var item in something)
{
var result = await GetAsync();
return // what?
}
}
(Edited)
Using System.Linq.Async 4.0.0 from NuGet, now you can use SelectAwait.
class Program
{
static void Main(string[] args)
{
Task.Run(async () =>
await GetAllAsync().ForEachAsync((x) => Console.WriteLine(x)));
Thread.Sleep(4000);
}
static IAsyncEnumerable<string> GetAllAsync()
{
var something = new[] { 1, 2, 3 };
return something
.ToAsyncEnumerable()
.SelectAwait(async (x) => await GetAsync(x));
}
static async Task<string> GetAsync(int item)
{
await Task.Delay(1000); // heavy
return "got " + item;
}
}
(Obsolete)
Using System.Interactive.Async 3.2.0 from NuGet, how about this? Currently Select() does not support async lambda, you have to implement it by yourself.
Better support for async - Task based overloads for AsyncEnumerable
class Program
{
static void Main(string[] args)
{
Task.Run(async () =>
await GetAllAsync().ForEachAsync((x) => Console.WriteLine(x)));
Thread.Sleep(4000);
}
static IAsyncEnumerable<string> GetAllAsync()
{
var something = new[] { 1, 2, 3 };
return something.SelectAsync(async (x) => await GetAsync(x));
}
static async Task<string> GetAsync(int item)
{
await Task.Delay(1000); // heavy
return "got " + item;
}
}
static class AsyncEnumerableExtensions
{
public static IAsyncEnumerable<TResult> SelectAsync<T, TResult>(this IEnumerable<T> enumerable, Func<T, Task<TResult>> selector)
{
return AsyncEnumerable.CreateEnumerable(() =>
{
var enumerator = enumerable.GetEnumerator();
var current = default(TResult);
return AsyncEnumerable.CreateEnumerator(async c =>
{
var moveNext = enumerator.MoveNext();
current = moveNext
? await selector(enumerator.Current).ConfigureAwait(false)
: default(TResult);
return moveNext;
},
() => current,
() => enumerator.Dispose());
});
}
}
The extension method is quoted from this sample. https://github.com/maca88/AsyncGenerator/issues/94#issuecomment-385286972
I have a method that takes a Action<String>. When the method finishes its processing it calls the Action<String> with the return value.
MethodWithCallback((finalResponse)=> {
Console.WriteLine(finalResponse);
});
I want to use this in a web.api async controller. How do I wrap this method so I can await for this method to complete in an async manner. I cannot modify the method itself, it is in a legacy code base.
What I would like to be able to do is this
String returnValue = await MyWrapperMethodThatCallsMethodWithCallback();
You can leverage the TaskCompletionSource class and solve the problem in a generic way:
Task<T> AsAsync<T>(Action<Action<T>> target) {
var tcs = new TaskCompletionSource<T>();
try {
target(t => tcs.SetResult(t));
} catch (Exception ex) {
tcs.SetException(ex);
}
return tcs.Task;
}
That way you don't have to modify your MethodWhitCallback:
var result = await AsAsync<string>(MethodWithCallback);
Console.WriteLine(result);