I'm developing a Windows 8 Runtime Component so the public interface can't contain Task<T> as it's not a windows runtime type.
This means I can't mark the method as async and can't await the private async methods in my library. This is leading to some confusion about how to handle my application logic.
This is how I'd do what I want synchronously.
Result r = TryGetAuthResultFromFile();
if(r != null)
{
return r;
}
r = GetAuthResultFromWebAuthenticationBroker();
return r;
The problem is that TryGetResultFrom file are async Task<Result> methods and the method that's returning r is returning IAsyncOperation<Result>
I've tried this (this isn't complete code but the theory can be seen, handle the results in continuations and return them, I'd have to do some frigging of results to IAsyncOperation types).
TryGetAuthResultFromFile().ContinueWith(x=>
{
if(x.Result != null)
{
return x.result;
}
GetAuthResultFromWebAuthenticationBroker().ContinueWith(y=>
{
return y.Result;
});
});
The problem with this is that the WebAuthenticationBroker doesn't seem work if it's not being called from the UI thread. It throws a helpful NotImplementedException without a useful error message.
How can I call TryGetAuthResultFromFile then wait for the result, then call GetAuthResultFromWebAuthenticationBroker?
Your interface can't use Task/Task<T>, but it can use IAsyncAction/IAsyncOperation<T>.
Your implementation can use Task/Task<T> if you have a wrapper that calls AsAsyncAction/AsAsyncOperation/AsyncInfo.Run as appropriate.
public interface IMyInterface
{
IAsyncOperation<MyResult> MyMethod();
}
public sealed class MyClass: IMyInterface
{
private async Task<MyResult> MyMethodAsync()
{
var r = await TryGetAuthResultFromFileAsync();
if (r != null)
return r;
return await GetAuthResultFromAuthenticationBrokerAsync();
}
public IAsyncOperation<MyResult> MyMethod()
{
return MyMethodAsync().AsAsyncOperation();
}
}
Related
I am overriding a method in a base class library. However, inside my overridden implementation I am using the new HttpClient which is all based on async methods. I therefore have to mark my method as async, which means that I need to change the return parameter of the method from string to Task. The compiler however gives an error: "The return type must be 'string' to match overridden member ...."
public class BaseClass
{
public virtual string GetName()
{
...
}
}
public class MyClass : BaseClass
{
public override async Task<string> GetName()
{
HttpClient httpClient = new HttpClient();
var response = await httpClient.GetAsync("");
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
return await responseContent.ReadAsStringAsync();
}
return null;
}
}
Of course the obvious solution would be to change the return type of GetName() in BaseClass to Task<string>, but I have no control over BaseClass as it is an external library;
My current solution is to use the HttpClient classes in a synchronous fashion, i.e. change MyClass as follows:
public class MyClass : BaseClass
{
public override string GetName()
{
HttpClient httpClient = new HttpClient();
var response = httpClient.GetAsync("");
if (response.Result.IsSuccessStatusCode)
{
var responseContent = response.Result.Content;
return responseContent.ReadAsStringAsync()
.Result;
}
return null;
}
}
Is there any other way to do this?
Unfortunately there isn't a good solution here. There is no way to override a non-async method with an async one. I think your best bet is to have an async non-override method and call into that from the non-async one:
public class MyClass : BaseClass
{
public override string GetName()
{
return GetNameAsync().Value;
}
public async Task<string> GetNameAsync()
{
...
}
}
Note that this can cause problems though. If the original code didn't expect for any async code to be executing introducing this pattern could break expectations. I would avoid it if possible.
Luckily the ReadAsStringAsync().Result is not causing a deadlock since it is likely to have ConfigureAwait(false) within.
To prevent a deadlock, you could use one of the following methods:
public static T GetResult<T>(Func<Task<T>> func)
{
var httpContext = HttpContext.Context;
var proxyTask = Task.Run(() =>
{
HttpContext.Context = httpContext;
return func();
});
return proxyTask.Result;
}
// or
public static T GetResult<T>(Func<Task<T>> func)
{
var syncContext = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(null);
var task = func();
SynchronizationContext.SetSynchronizationContext(syncContext);
return task.Result;
}
This way you would call
public override string GetName()
{
...
return GetResult(() => responseContent.ReadAsStringAsync());
...
}
The former has a performance overhead by spawning a new thread, while the latter suffers from breaking SynchronizationContext flow, which makes any context bound to it unavailable in the task being called, e.g. HttpContext.Current.
I've also had this problem, and the solution was using an interface, in which 'async' isn't part of the method's signature.
public abstract class Base : IInvokable {
/* Other properties ... */
public virtual async Task Invoke() {
/*...*/
}
}
public interface IInvokable {
Task Invoke();
}
public class Derived
{
public override async Task Invoke() {
// Your code here
}
}
I'm working on a class responsible for communicating with O365 using the Microsoft Graph Client Library. In each method, the call to NextPageRequest.GetAsync() is on a different type which also returns a different type, but otherwise the pagination logic is identical:
public async Task<List<Microsoft.Graph.User>> FindAllUsers()
{
var usersFound = new List<Microsoft.Graph.User>();
var usersPage = await GraphClient.Users.Request().GetAsync();
usersFound.AddRange(usersPage);
while (usersPage.NextPageRequest != null)
{
usersPage = await usersPage.NextPageRequest.GetAsync();
usersFound.AddRange(usersPage);
}
return usersFound;
}
public async Task<List<Microsoft.Graph.Group>> FindAllGroups()
{
var groupsFound = new List<Microsoft.Graph.Group>();
var groupsPage = await GraphClient.Groups.Request().GetAsync();
groupsFound.AddRange(groupsPage);
while (groupsPage.NextPageRequest != null)
{
groupsPage = await groupsPage.NextPageRequest.GetAsync();
groupsFound.AddRange(groupsPage);
}
return groupsFound;
}
public async Task<List<Microsoft.Graph.User>> FindGroupMembers(string groupId)
{
var usersFound = new List<Microsoft.Graph.User>();
var membersPage = await GraphClient.Groups[groupId].Members.Request().GetAsync();
usersFound.AddRange(membersPage.Where(d => d.ODataType.Equals("#microsoft.graph.user")).Cast<Microsoft.Graph.User>());
while (membersPage.NextPageRequest != null)
{
membersPage = await membersPage.NextPageRequest.GetAsync();
usersFound.AddRange((List<Microsoft.Graph.User>)membersPage);
}
return usersFound;
}
I would like to write generic method to reduce duplication, but in each of the above methods, the return type of GetAsync is a different interface that defines its own NextPageRequest property on itself. This makes it impossible to tell the generic method what specific type it will need to call NextPageRequest on so that the method can compile.
Is there a way to improve upon this, or do I just need to accept the duplicated logic for each query type I want to implement?
Thanks to Microsoft Graph API architects, it looks like we can only get rid of such sort of redundancy either by using reflection or dynamics. Since dynamics, in theory, should provide better performance, here's a version of sample code based on them:
private void ProcessAllResultPages<TResult, TItem>(IBaseRequest request,
Action<TResult> processorDelegate)
where TResult : ICollectionPage<TItem>
{
do
{
Task<TResult> task = ((dynamic)request).GetAsync();
processorDelegate(task.Result); // This will implicitly call Wait() on the task.
request = ((dynamic)task.Result).NextPageRequest;
} while (request != null);
}
Sample usage:
IGraphServiceGroupsCollectionRequest request = graphServiceClient.Groups.Request().
Filter(...).
Select(...).
Top(pageSize);
ProcessAllResultPages<IGraphServiceGroupsCollectionPage, Group>(request,
result =>
{
// Process page results here.
});
I used this to reduce duplication of code:
public async Task<List<T>> GetAllAsync<T>(IBaseRequest baseRequest)
where T : DirectoryObject
{
List<T> pagedItems = new();
try
{
var pageOfItems = await ((dynamic)baseRequest).GetAsync();
pagedItems.AddRange(pageOfItems);
while (pageOfItems.NextPageRequest != null)
{
pageOfItems = await pageOfItems.NextPageRequest.GetAsync();
pagedItems.AddRange(pageOfItems);
}
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
}
return pagedItems;
}
And then use it with:
var result = await GetAllAsync<Microsoft.Graph.Group>(_graphServiceClient.Groups.Request());
var result = await GetAllAsync<Microsoft.Graph.User>(_graphServiceClient.Users.Request());
I'm trying to make an exception interceptor in my Xamarin application. Right now I'm juste trying to intercept service's methods: the call from view model to buisiness logic (all in one project, full .net standard 2).
I fall upon this answer (using autofac) and found it simple and clever. It works fine, I add a try-catch to get my exception, so far so good.
But then I tried to return my exception in a DTO object type. All our services return a Task of a DTO class derived from a DTOBase abstract class. Theses classes just hold a reference to the value(s) and a IEnumerable of exception named Errors.
So basically, I try to catch the exception, put it in the list of Errors and return my object. I finished with this code :
public class ExceptionInterceptorBehaviour : IInterceptor
{
public void Intercept(IInvocation invocation)
{
invocation.Proceed();
var method = invocation.MethodInvocationTarget;
var isAsync = method.GetCustomAttribute(typeof(AsyncStateMachineAttribute)) != null;
if (isAsync && typeof(Task).IsAssignableFrom(method.ReturnType))
{
invocation.ReturnValue = InterceptAsync((dynamic)invocation.ReturnValue);
}
}
private static async Task InterceptAsync(Task task)
{
await task.ConfigureAwait(false);
}
private static async Task<T> InterceptAsync<T>(Task<T> task)
{
try
{
T result = await task.ConfigureAwait(false);
return result;
}
catch (Exception e)
{
if (typeof(DTOBase).IsAssignableFrom(typeof(T)))
{
var ret = Activator.CreateInstance(typeof(T));
(ret as DTOBase).Errors.Add(e);
return (T)ret;
}
throw e;
}
}
}
My probleme is that the application crashes at the return of Task<T> InterceptAsync<T>(Task<T> task). No exception is raised, no pause mode in the debugger just a plain crash.
I suspect a segmentation error, but my cast does work (I tested it) and I do return a Task<T> and assign it to a Task<T> object.
Am I missing something? I don't get why it crashes like that.
Is that happening on iOS? Xamarin has some limitations defined by its underlying platforms. Dynamic code is one of them. Avoid using dynamic.
So, I took account of rubo's answer and rewrite my code with no dynamic variable and end up with this :
public class ExceptionInterceptorBehaviour : IInterceptor
{
public void Intercept(IInvocation invocation)
{
invocation.Proceed();
var method = invocation.MethodInvocationTarget;
var isAsync = method.GetCustomAttribute(typeof(AsyncStateMachineAttribute)) != null;
if (isAsync && typeof(Task).IsAssignableFrom(method.ReturnType))
{
if (method.ReturnType.IsGenericType)
{
invocation.ReturnValue = typeof(ExceptionInterceptorBehaviour)
.GetMethod("InterceptGenericAsync", BindingFlags.Instance | BindingFlags.NonPublic)
.MakeGenericMethod(method.ReturnType.GenericTypeArguments[0])
.Invoke(this, new object[] { invocation.ReturnValue });
}
else
{
invocation.ReturnValue = InterceptAsync((Task)invocation.ReturnValue);
}
}
}
private async Task InterceptAsync(Task task)
{
await task.ConfigureAwait(false);
}
private async Task<T> InterceptGenericAsync<T>(Task<T> task)
{
try
{
object result = await task.ConfigureAwait(false);
return (T)result;
}
catch (Exception e)
{
if (typeof(DTOBase).IsAssignableFrom(typeof(T)))
{
var ret = Activator.CreateInstance(typeof(T));
(ret as DTOBase).Errors.Add(e);
return (T)ret;
}
throw e;
}
}
}
The fun fact is that code was still crashing when I tried to step out of InterceptGenericAsync in debug, but it works just fine if I let it run, which is weird and scary.
I did not test this solution on iOS though, I'm not sure it's working.
I have this method:
public object LongRunningTask()
{
return SomethingThatTakesTooLong();
}
I wrote the following code so I can transform a normal method in an async one and still get the Exception:
public async Task<object> LongRunningTaskAsync()
{
Exception ex = null;
object ret = await Task.Run(() =>
{
object r = null;
try
{
//The actual body of the method
r = SomethingThatTakesTooLong();
}
catch (Exception e)
{
ex = e;
}
return r;
});
if (ex == null)
return ret;
else
throw ex;
}
When I need to do this in several methods, I have to copy all this code and change only the middle.
Is there a way to do something like this?
[SomeAttributeThatDoesThatMagically]
public async Task<object> LongRunningTaskAsync()
{
return SomethingThatTakesTooLong();
}
Attributes are generally metadata though it is possible to define attributes that can be executed (such as security behaviours in WCF) however, something has to be looking for it first. Your attributes won't just magically run.
I suspect you might have to use a dynamic proxy.
Take a look at how WCF does things for ideas.
I have a system which uses AOP with ContextBoundObject.
This is used to intercept a method call and perform certain operations before and after the function. It all works fine until I make the 'function to be intercepted' async.
I understand that the C# compiler rewrites async methods into a state machine, which returns control to the sink as soon as 'await' is reached
So it continues into the interception and executes the code which is meant to be executed only after the Method.
I can see there is an "AsyncProcessMessage" in IMessageSink, but I can't find a way to invoke it, and I am not sure if it will work in the async/await scenario.
Is there a way to make Async/Await work with the ContextBoundObject? Is using another Aspect Oriented Programming approach the only option here?
The code sample below has the method to be intercepted decorated with the 'Audit' attribute and placed in the AuditFacade which is a ContextBoundObject. The SyncProcessMessage method in the AuditSink has the logic to be executed before and after the method.
[AuditBoundary]
public class AuditFacade : ContextBoundObject
{
[Audit]
public ResponseObject DoSomthing()
{
//Do something
return new ResponseObject();
}
/// <summary>
/// Async Method to be intercepted
/// </summary>
/// <returns></returns>
[Audit]
public async Task<ResponseObject> DoSomthingAysnc()
{
//Do something Async
await Task.Delay(10000);
return new ResponseObject();
}
}
[AttributeUsage(AttributeTargets.Method)]
public class AuditAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class)]
public class AuditBoundaryAttribute : ContextAttribute
{
public AuditBoundaryAttribute()
: base("AuditBoundary" + Guid.NewGuid().ToString())
{
}
public override void GetPropertiesForNewContext(IConstructionCallMessage ctorMsg)
{
ctorMsg.ContextProperties.Add(new AuditProperty());
}
}
public class AuditProperty : IContextProperty, IContributeObjectSink
{
public string Name
{
get { return "AuditProperty"; }
}
public bool IsNewContextOK(Context newCtx)
{
var p = newCtx.GetProperty("AuditProperty") as AuditProperty;
if (p == null)
return false;
return true;
}
public void Freeze(Context newContext)
{
}
public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink nextSink)
{
return new AuditSink(nextSink);
}
}
public class AuditSink : IMessageSink
{
private IMessageSink nextSink;
public AuditSink(IMessageSink nextSink)
{
this.nextSink = nextSink;
}
public IMessage SyncProcessMessage(IMessage msg)
{
var message = msg as IMethodCallMessage;
IMethodReturnMessage returnMessage = null;
ResponseObject response;
//Some Pre Processing happens here
var newMessage = new MethodCallMessageWrapper(message);
//Invoke the Method to be Audited
returnMessage = nextSink.SyncProcessMessage(newMessage) as IMethodReturnMessage;
response = returnMessage.ReturnValue as ResponseObject;
//Some Post Processing happens here with the "response"
return returnMessage;
}
public IMessageSink NextSink
{
get { return this.nextSink; }
}
public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
{
return nextSink.AsyncProcessMessage(msg, replySink);
}
}
I don't know anything about ContextBoundObject, but I think that AsyncProcessMessage() has nothing to do with async-await and that the following should work using the normal SyncProcessMessage():
Do your preprocessing step.
Invoke the async method.
Add your postprocessing step as a continuation to the returned Task, using ContinueWith() or await.
Return the continuation Task to the caller.
If you're okay with your postprocessing executing on the thread pool, then ContinueWith() is probably simpler. If you need the postprocessing to execute on the original context, use await.
The await version could look like this:
var responseTask = (Task<ResponseObject>)returnMessage.ReturnValue;
Func<Task<ResponseObject>> postProcessTaskFunc = async () =>
{
var response = await responseTask;
// Some Post Processing happens here with the "response"
return response;
}
return new ReturnMessage(postProcessTaskFunc(), …);