I have an implementation like this:
Task<IEnumerable<Item1>> GetItems1()
{
return RunRequest(async () => ParseItemsFromResponse(await(httpClient.Get(..))));
}
Task<IEnumerable<Item2>> GetItems2()
{
return RunRequest(async () => ParseItemsFromResponse(await httpClient.Get(..)));
}
TResult RunRequest<TResult>(Func<TResult> req)
{
try
{
return req();
}
catch (Exception ex)
{
// Parse exception here and throw custom exceptions
}
}
The issue is the void anonymous method async () => ParseItemsFromResponse(..).
Since it returns void and not a Task, if there's an exception thrown within the anonymous method, it's actually not going to be caught by the try and catch within the RunRequest.
Any suggestions how to refactor this?
RunRequest should take a Func<Task<TResult>>, as such:
async Task<TResult> RunRequestAsync<TResult>(Func<Task<TResult>> req)
{
try
{
return await req().ConfigureAwait(false);
}
catch (Exception ex)
{
// Parse exception here and throw custom exceptions
}
}
Then your async lambdas are converted to async Task<T> methods instead of async void.
I have more information on sync/async delegates on my blog.
Related
Hello I want to catch a Exception of a async method but it did not work look a this example :
public void TryToCatchException()
{
try
{
_ =LongRunningMethod();
}
catch (MyException)
{
Console.WriteLine("catched");
}
}
public static async Task LongRunningMethod()
{
await Task.Run(() =>
{
try
{
Task.Delay(1000); //simulation of work
throw new ArgumentException(); // this is a example
}
catch (ArgumentException)
{
throw new MyException;
}
});
}
if I launch the debugger will say that the exception "MyException" is NOT catched... can someone help me ?
When you discard tasks, those exceptions are not observed:
_ =LongRunningMethod();
If you want to catch exceptions from LongRunningMethod, then you need to await the task returned from that method:
await LongRunningMethod();
I have a class called SearchProbe for I'm writing unit tests. One unit test is for testing the ability of my class's main processing method (called RunSearchProbe) to be able to respond to CancellationTokens correctly. My class's main processing method executes async submethods which all throw an OperationCanceledException when a CancellationToken is cancelled. Then in my main method RunSearchProbe, I'm trying to catch this exception and respond to it.
Problem: The problem is that for some reason, OperationCanceledException is NOT being caught in the main method RunSearchProbe, and it comes all the way upto my unit test's call stack for handling, and I don't know why ?!
Here's my main class:
public class SearchProbe
{
protected async Task RunSearchProbe(CancellationToken cancellationToken) {
try
{
try
{
using (cancellationToken.Register(() => {
//some code here
}))
{
Task<bool> initTask = Initialize(cancellationToken);
await initTask;
//some code here
}
}
catch (Exception exception) when (exception.GetType().Equals(typeof(OperationCanceledException))
|| exception.InnerException.GetType().Equals(typeof(OperationCanceledException)))
{
//some code here // -------->>> (Point 1) This is where the OperationCanceledException SHOULD get caught
}
finally
{
//some code here
}
}
catch (Exception e)
{
//some code here // -------->>> (Point 2) ... Or AT LEAST get caught here
}
}
private async Task<bool> Initialize(CancellationToken cancellationToken) {
try
{
using (cancellationToken.Register(() => {
throw new OperationCanceledException();
}))
{
//some code here
return true;
}
}
catch (Exception exception)
{
//some code here
}
}
}
This is a mock inherited class:
class MockSearchProbe : SearchProbe
{
static MockSearchProbe()
{
//some code here
}
public async Task RunProbeManually()
{
try {
CancellationTokenSource cts = new CancellationTokenSource();
Task probeTask = RunSearchProbe(cts.Token);
cts.Cancel();
await probeTask;
}
catch (Exception exception) when (exception.GetType().Equals(typeof(OperationCanceledException))
|| exception.InnerException.GetType().Equals(typeof(OperationCanceledException)))
{
//do something (Point 3) ... But it actually gets caught here for some reason
}
}
}
This is the test class:
[TestClass]
public class SearchProbeTests
{
[TestMethod]
public async Task TestProbe_Cancellation()
{
MockSearchProbe probe = new MockSearchProbe();
Task result = probe.RunProbeManually();
await result;
}
}
Please see steps 1, 2 and 3 commented above to see what I mean ... Why is the catch block inside my main class's RunSearchProbe method NOT catching the OperationCanceledException ??
The documentation for CancellationToken.Regsiter states that the method:
Registers a delegate that will be called when this CancellationToken is canceled.
Based on that description, I would expect that the registration callback defined in the Initialize method should execute when cts.Cancel() is called in RunProbeManually. The exception is not instantiated or thrown until that point, which is in the scope of the try/catch block labeled "Point 3."
Here's a simplified illustration:
using System;
class MainClass {
public static void Main (string[] args) {
Action throwException = null;
try {
Console.WriteLine("Defining delegate");
throwException = () => {
Console.WriteLine("Throwing exception");
throw new Exception();
};
} catch (Exception) {
Console.WriteLine("Exception caught at point 1");
}
try {
Console.WriteLine("Invoking delegate");
throwException.Invoke();
} catch (Exception) {
Console.WriteLine ("Exception caught at point 2");
}
}
}
Output:
Defining delegate
Invoking delegate
Throwing exception
Exception caught at point 2
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;
}
}
Let's say I have an Interface:
interface A {
string Do();
}
and then I implement this interface in a class. The implementation requires some async operations. Something like the following:
class B : A {
public string Do() {
return Task1().Result;
}
private async Task<string> Task1() {
var str = await Task2();
return str + "task1";
}
private async Task<string> Task2() {
using (WebClient client = new WebClient())
{
return System.Text.Encoding.UTF8.GetString(await client.DownloadDataTaskAsync(new Uri("http://test.com")));
}
}
}
What is the proper way to return, to the external calling code, the first exception that occurs in the async operations chain? Is the following a good approach?
public string Do() {
try {
return Task1().Result;
} catch (AggregateException ex) {
Exception inner = ex;
while(inner.InnerException != null) {
inner = inner.InnerException;
}
throw inner;
}
}
From your code, through the while, I think you want to throw the first exception in AggregateException
To do that, you can use Flatten
Flattens an AggregateException instances into a single, new instance.
It helps to put the exceptions in "the same hierarchy", you can then simply call FirstOrDefault to get the first exception.
Supposed this code:
Task.Factory.StartNew(
async () =>
{
await Task.Factory.StartNew(
() => { throw new Exception("inner"); },
TaskCreationOptions.AttachedToParent);
throw new Exception("outer");
}).Wait();
}
The stucture of exceptions likes
AggregateException
Exception: outer
AggregateException
Exception: inner
With Flatten, I can get inner
catch(AggregateException ex)
{
Console.WriteLine(ex.Flatten().InnerExceptions.FirstOrDefault().Message);
}
but without Flatten, I get AggregateException, which isn't correct
catch(AggregateException ex)
{
Console.WriteLine(ex.Flatten().InnerExceptions.FirstOrDefault().Message);
}
With your case, this line can help you get the first exception
ex.Flatten().InnerExceptions.FirstOrDefault().Message
You have also the method Handle, which help you handle the exception inside AggregateException
catch (AggregateException ex)
{
ex.Handle(x =>
{
if (x is UnauthorizedAccessException)
{
//the exception you interested
throw x;
}
// Other exceptions will not be handled here.
//some action i.e log
return false;
});
}
New to async await integration in C# 5. I'm working with some basic Task based methods to explore async await and the TPL. In this example below I'm calling a web service with a timeout of 5 seconds. If the timeout expires it should throw an exception so I can return false from the method. However, the timeout never occurs, or maybe it does but the Task never returns.
public static Task<bool> IsConnectedAsync()
{
return Task.Run(() =>
{
try
{
using (WSAppService.AppService svc = new NCSoftware.Common.WSAppService.AppService(GetServiceUrl(WebService.app)){Timeout = 5000})
{
return svc.PingB();
}
}
catch (Exception ex)
{
Logger.LogException(ex.Message, ex, "IsConnectedAsync");
}
return false;
});
}
If you could please help with how to properly handle this so that if the timeout occurs or even better, an exception occurs, the Task does return.
In general, you shouldn't use Task.Run if you're wrapping async services. Since this is a service reference, you should be able to expose an async method (returning Task) directly from the service, in which case you could use:
public async static Task<bool> IsConnectedAsync()
{
try
{
using (WSAppService.AppService svc = new NCSoftware.Common.WSAppService.AppService(GetServiceUrl(WebService.app)){Timeout = 5000})
{
return await svc.PingBAsync();
}
}
catch (Exception ex)
{
Logger.LogException(ex.Message, ex, "IsConnectedAsync");
}
return false;
}
If you must wrap via Task.Run (again, this is not suggested, as it's turning synchronous code into async via the thread pool, which is typically better handled by the user at the top level), you could do:
public async static Task<bool> IsConnectedAsync()
{
try
{
return await Task.Run(() =>
{
using (WSAppService.AppService svc = new NCSoftware.Common.WSAppService.AppService(GetServiceUrl(WebService.app)){Timeout = 5000})
{
return svc.PingB();
}
}
}
catch (Exception ex)
{
Logger.LogException(ex.Message, ex, "IsConnectedAsync");
return false;
}
}