How to make a unversal timeoutable function wrapper in C#? - c#

I have a bunch of functions with blocking calls which could hang in case of network connectivity loss or other issues. I want to make an universal wrapper allowing to run passed function with specified timout and arguments.
A function prototypes:
public static double Func1(string ip, string username, string password);
public static int Func2(string ip, string username, string password, string dir);
My wrapper:
public static T? ExecuteAsync<T>(Func<object[], T> func, int timeout /* sec */, params object[] args) where T : struct
{
var task = Task.Factory.StartNew(() => func(args));
if (task.Wait(timeout * 1000))
return task.Result;
return null;
}
Expected usage:
var res1 = ExecuteAsync<double>(Func1, 30, "1.1.1.1", "user", "looser");
var res2 = ExecuteAsync<int>(Func2, 20, "1.1.1.1", "user", "looser", "home");
Compiler errors here (on line with call to ExecuteAsync):
Error CS1503 Argument 1: cannot convert from 'method group' to 'Func'
I found a compilable code
var res = ExecuteAsync((args) => Func1(args[0].ToString(), args[1].ToString(), args[2].ToString()), 50, "ip", "user", "pass");
It is too heavy and unreadable. Is it possible to simplify it? How to fix original error? Maybe there is an another way to reach the goal?
I see examples with Action, but my functions are returning a value and they have different argument list.

The problem you have is the signature of Func1 has three string args whereas your ExecuteAsync method's first arg expects a "method" with object array as the argument
i.e. object[] != string, string, string
public static double Func1(string ip, string username, string password);
Func<object[], T>
The simplest solution you can have is to standardize the signature of all the "blocking functions". In that case your situation would look like below code. You lose type-safety in this. This approach is used by the Thread class
static void Main(string[] args) {
var res1 = ExecuteAsync<double>(Func1, 30, "1.1.1.1", "user", "looser");
}
public static double Func1(object[] args) {
string ip = (string)args[0], username = (string)args[1], password = (string)args[2];
// do some work
return 0.0;
}
public static T? ExecuteAsync<T>(Func<object[], T> func, int timeout /* sec */, params object[] args) where T : struct {
var task = Task.Factory.StartNew(() => func(args));
if (task.Wait(timeout * 1000))
return task.Result;
return null;
}
If you don't want to lose type safety, you can create multiple overloads of the ExecuteAsync method - similar to how .NET framework creates multiple overloads for Func. In that case, you ExecuteAsync method will look like below. You can create other overloads for 1, 2, 4, 5 arg methods just like how Func is implemented
public static TRes? ExecuteAsync<T1, T2, T3, TRes>(Func<T1, T2, T3, TRes> func, int timeout /* sec */, T1 arg1, T2 arg2, T3 arg3) where TRes : struct {
var task = Task.Factory.StartNew(() => func(arg1, arg2, arg3));
if (task.Wait(timeout * 1000))
return task.Result;
return null;
}

Related

Implement calling delegate with out parameters

I try to implement a decorator pattern for handling error in database transactions. I have no problem with standard Func and Actions, but i have difficulties with functions having out parameter.
Here many topics with same question, and i figured out to implement my own delegate:
public delegate TResult FuncWithOut<T1, T2, TResult>(T1 arg1, out T2 arg2);
1) But i don't found how to implement method based on this delegate:
private void SafetyExecuteMethod(Action action)
{
try
{
action();
}
catch (Exception ex)
{
// Some handling
}
}
private T SafetyExecuteFunction<T>(Func<T> func)
{
T result = default(T);
SafetyExecuteMethod(() => result = func.Invoke());
return result;
}
private SafetyExecuteFunctionWithOut // ??
{
// ??
}
2) And how to call this method:
public bool UserExists(string name)
{
return SafetyExecuteFunction(() => _innerSession.UserExists(name));
}
public void CreateUser(string name, string password)
{
SafetyExecuteMethod(() => _innerSession.CreateUser(name, password));
}
public bool CanUpdateUser(string userName, out string errorMessage)
{
// ??
// _innerSession.CanUpdateUser(userName, out errorMessage);
}
Just use the same scheme as in your example of SafetyExecuteFunction<T>(Func<T> func).
One thing you have to pay attention to is that you need to use a temporary local variable for the out parameter.
private TResult SafetyExecuteFunctionWithOut<T1, T2, TResult>(FuncWithOut<T1, T2, TResult> func, T1 arg1, out T2 arg2)
{
TResult result = default(TResult);
T2 arg2Result = default(T2); // Need to use a temporary local variable here
SafetyExecuteMethod(() => result = func(arg1, out arg2Result));
arg2 = arg2Result; // And then assign it to the actual parameter after calling the delegate.
return result;
}
Calling the function does then work like this:
public bool CanUpdateUser(string userName, out string errorMessage)
{
bool result = SafetyExecuteFunctionWithOut<string, string, bool>(_innerSession.CanUpdateUser, userName, out errorMessage);
return result;
}
Note, that you have to pass _innerSession.CanUpdateUser as a parameter to SafetyExecuteFunctionWithOut instead of using a lambda expression.
Using the naive attempt:
private TResult SafetyExecuteFunctionWithOut<T1, T2, TResult>(FuncWithOut<T1, T2, TResult> func, T1 arg1, out T2 arg2)
{
TResult result = default(TResult);
SafetyExecuteMethod(() => result = func(arg1, out arg2));
return result;
}
creates the error message:
CS1628 Cannot use ref or out parameter 'arg2' inside an anonymous
method, lambda expression, or query expression
Why you are not allowed to do that is explained in this answer.

Generic function declaration in C#

I'm trying to create some stats about method call duration in a library.
Instead of wrapping each method call to the library with lines to time and track it, I want to create a generic action and function which does these recurring steps.
E.g. for methods that don't return a value, I have created this:
private readonly Action<string, Action> timedAction = (name, action) =>
{
var sw = Stopwatch.StartNew();
action.Invoke();
trackDuration(name, sw.ElapsedMilliseconds);
};
That can be invoked with timedAction("methodname", () => lib.methodname()).
I want to do something similar for methods that return a value, but obviously Action can't be used for that purpose, since it can't return a value.
Is there a way to do this with a generic Func, so I don't have to declare one for each combination of library method parameters?
You can use a generic function like this:
private static TValue FuncHandler<TValue>(string name, Func<TValue> func)
{
var sw = Stopwatch.StartNew();
var result = func();
trackDuration(name, sw.ElapsedMilliseconds);
return result;
}
Call it like this:
var result = FuncHandler("name", () => MyMethod(param1));
Indeed, AOP will buy you more than this sort of tediousness:
https://dotnetfiddle.net/5PLCmM
// Needs to be replicated after Func<T1, TResult>, Func<T1, T2, TResult>, etc, for all the functions arities you'll want to wrap with it
public static TResult Timed<T1, /*T2, etc*/TResult>(out long duration, Func<T1, /*T2, etc*/TResult> func, T1 arg1/*T2 arg2, etc*/)
{
//start timing
var t0 = DateTime.Now;
var result = func(arg1/*, arg2, etc*/);
//end timing
duration = (long)DateTime.Now.Subtract(t0).TotalMilliseconds;
return result;
}
public int Factorial(int n)
{
return n > 0 ? n * Factorial(n - 1) : 1;
}
public int Fibonacci(int n)
{
return n > 1 ? Fibonacci(n - 2) + Fibonacci(n - 1) : n;
}
public static void Main()
{
var program = new Program();
long duration;
var _12bang = Timed(out duration, program.Factorial, 12);
Console.WriteLine("{0}! = {1} in {2} ms", 12, _12bang, duration);
var fib31 = Timed(out duration, program.Fibonacci, 31);
Console.WriteLine("Fib {0} = {1} in {2} ms", 31, fib31, duration);
}
(yes, I know about StopWatch; was just too lazy to put it in there)
'Hope this helps.
In your case AOP will be more tedious. Here is my solution which works:
Class1.cs
using System;
namespace ClassLibrary1
{
public class Class1
{
public void WriteNoParam()
{
Console.WriteLine("void");
}
public void WriteWithParam(string name)
{
Console.WriteLine("My name is: " + name);
}
}
}
Program.cs
using System;
namespace ConsoleApplication2
{
using System.Diagnostics;
using System.Reflection;
using ClassLibrary1;
class Program
{
static void Main(string[] args)
{
var prReflection = new TestReflection<Class1>();
var elapsed = prReflection.TestFunc(new Class1(), #"C:\Users\yasir\Documents\visual studio 2013\Projects\ConsoleApplication2\ClassLibrary1\bin\Debug\ClassLibrary1.dll", "WriteNoParam", new string[0]);
Console.WriteLine("Elapsed time for non parameter method: "+elapsed);
elapsed = prReflection.TestFunc(new Class1(), #"C:\Users\yasir\Documents\visual studio 2013\Projects\ConsoleApplication2\ClassLibrary1\bin\Debug\ClassLibrary1.dll", "WriteWithParam", new[]{"Yasir"});
Console.WriteLine("Elapsed time for parameter method: " + elapsed);
Console.ReadLine();
}
}
public class TestReflection<T> where T: class
{
public Func<T, string, string, string[], long> TestFunc = (arg1, s, s2, arr) =>
{
var assembly = Assembly.LoadFile(s);
var type = assembly.GetType(typeof (T).ToString());
long executionTime;
if (type != null)
{
var methodInfo = type.GetMethod(s2);
if (methodInfo != null)
{
ParameterInfo[] parameters = methodInfo.GetParameters();
object classInstance = Activator.CreateInstance(type, null);
var stopWatch = new Stopwatch();
if (parameters.Length == 0)
{
// This works fine
stopWatch.Start();
methodInfo.Invoke(classInstance, null);
return stopWatch.ElapsedMilliseconds;
}
stopWatch.Start();
methodInfo.Invoke(classInstance, arr); ;
return stopWatch.ElapsedMilliseconds;
}
}
return 0;
};
}
}
I have run in debug mode to test if the console is able to output in milliseconds and it works.
If you don't run in debug, execution will be really fast and console will output 0.
I know this question already has an answer, but I think this solution can be interesting, if you don't want to have to pass the name, yourself, each time, you could do this:
(It was a lot inspired by #selami' answer.)
private MemberInfo GetMethodName<T>(Expression<T> expression)
{
Expression body = expression.Body;
// You might want to complete this
// depending on which expression you want to use
return ((MethodCallExpression)body).Method.Name;
}
// Works for both Action and Func
private object TimedMethodInvoke<T>(Expression<T> funcExpression)
{
var sw = Stopwatch.StartNew();
var result = ((Delegate)(object)funcExpression.Compile()).DynamicInvoke();
trackDuration(GetMethodName(funcExpression), sw.ElapsedMilliseconds);
return result;
}
And your final methods:
public void TimeMethod(Expression<Action> actionExpression)
{
TimedMethodInvoke(actionExpression);
}
public TValue TimeMethod<TValue>(Expression<Func<TValue>> funcExpression)
{
return (TValue)TimedMethodInvoke(funcExpression);
}
I didn't run a benchmark over this solution, but I guess you should encounter a little performance hit, but if you don't mind about that and want to avoid to type the name each time, this could help.

Generic method to wrap function with different parameters number, int return and output parameter [duplicate]

This question already has answers here:
Func<T> with out parameter
(4 answers)
Closed 6 years ago.
I have a service (3-rd party) with a lot of methods with signatures like:
int MethodA(int, string, out T result)
int MethodB(int, string, string, out T[] result)
int MethodC(DateTime, string, string, out T result)
Where returning int is just a response code, and I actually need T's.
After each call I have an error logging logic (basically calling error handling method with response code as argument).
I wanted something like:
private T GenericDataExtractor<T>(Func function) {
T result;
int responseCode = function(out result);
if(responseCode != 0)
/* handling here */
return result;
}
But there is no way to pass output parameter as argument to func.
UPDATE
As I mentioned in service example, it's important for me to pass delegate with generic arguments. In other words I want a method, that accepts a functions with different number of arguments, but with fixed return type and generic out parameter.
IN THE END
Well, I ended up with this solution:
protected delegate int KeeperAPIDelegate<TReturn>(string sessionID, out TReturn rObj);
protected delegate int KeeperAPIDelegate<T1, TReturn>(string sessionID, T1 obj1, out TReturn rObj);
protected delegate int KeeperAPIDelegate<T1, T2, TReturn>(string sessionID, T1 obj1, T2 obj2, out TReturn rObj);
protected delegate int KeeperAPIDelegate<T1, T2, T3, TReturn>(string sessionID, T1 obj1, T2 obj2, T3 obj3, out TReturn rObj);
protected TReturn DataGrabber<TReturn>(KeeperAPIDelegate<TReturn> action)
{
TReturn data;
int result = action.Invoke(SessionID, out data);
if (result == 0) return data;
throw HandleError(result);
}
protected TReturn DataGrabber<T1, TReturn>(KeeperAPIDelegate<T1, TReturn> action, params object[] args)
{
TReturn data;
int result = action.Invoke(SessionID, (T1)args[0], out data);
if (result == 0) return data;
throw HandleError(result);
}
protected TReturn DataGrabber<T1, T2, TReturn>(KeeperAPIDelegate<T1, T2, TReturn> action, params object[] args)
{
TReturn data;
int result = action.Invoke(SessionID, (T1)args[0], (T2)args[1], out data);
if (result == 0) return data;
throw HandleError(result);
}
protected TReturn DataGrabber<T1, T2, T3, TReturn>(KeeperAPIDelegate<T1, T2, T3, TReturn> action, params object[] args)
{
TReturn data;
int result = action.Invoke(SessionID, (T1)args[0], (T2)args[1], (T3)args[2], out data);
if (result == 0) return data;
throw HandleError(result);
}
Guess it's not optimal, so any suggestions how to improve this will be highly appritiated.
Func doesn't not support out parameters, but there is no problem with custom delegate
public delegate int MyFunction<T>(out T parameter);
private T GenericDataExtractor<T>(MyFunction<T> function, out T result){
T result;
int responseCode = function(out result);
if(responseCode != null) /* handling here */
//the if above is always true :)
return result;
}

Is there a way to simplify this reflective delegate code in C#?

In this response, I came up with the following helper method that could be reused by different Task creators to convert events into task completion sources.
// Helper method
static Task<T> TaskFromEventHelper<T>(object target, string eventName, Func<TaskCompletionSource<T>, object> resultSetterFactory) {
var tcs = new TaskCompletionSource<T>();
var addMethod = target.GetType().GetEvent(eventName).GetAddMethod();
var delegateType = addMethod.GetParameters()[0].ParameterType;
var d = Delegate.CreateDelegate(delegateType, resultSetterFactory(tcs), "Invoke");
addMethod.Invoke(target, new object[] {d});
return tcs.Task;
}
// Empty events (Action style)
static Task TaskFromEvent(object target, string eventName) {
return TaskFromEventHelper(target, eventName, (Func<TaskCompletionSource<object>, object>)(tcs => (Action)(() => tcs.SetResult(null))));
}
// One-value events (Action<T> style)
static Task<T> TaskFromEvent<T>(object target, string eventName) {
return TaskFromEventHelper(target, eventName, (Func<TaskCompletionSource<T>, object>)(tcs => (Action<T>)(tcs.SetResult)));
}
// Two-value events (Action<T1, T2> or EventHandler style)
static Task<Tuple<T1, T2>> TaskFromEvent<T1, T2>(object target, string eventName) {
return TaskFromEventHelper(target, eventName, (Func<TaskCompletionSource<Tuple<T1, T2>>, object>)(tcs => (Action<T1, T2>)((t1, t2) => tcs.SetResult(Tuple.Create(t1, t2)))));
}
In each of the three examples I gave that use the helper method, there's a tcs.SetResult component, which makes me think there's a way to move that to the helper method too, which might perhaps simplify the signatures, so that perhaps the helper method would just have to accept a Func<?, T>, where that Func would take the output of the event and convert it to whatever tcs.SetResult takes.
i.e., I'm thinking there must be a way to create a helper so I can write it as
// Empty events (Action style)
static Task TaskFromEvent(object target, string eventName) {
return TaskFromEventHelper<object>(target, eventName, new Func<object>(() => null));
}
// One-value events (Action<T> style)
static Task<T> TaskFromEvent<T>(object target, string eventName) {
return TaskFromEventHelper<T>(target, eventName, new Func<T, T>(t => t));
}
// Two-value events (Action<T1, T2> or EventHandler style)
static Task<Tuple<T1, T2>> TaskFromEvent<T1, T2>(object target, string eventName) {
return TaskFromEventHelper<Tuple<T1, T2>>(target, eventName, new Func<T1, T2, Tuple<T1, T2>>(Tuple.Create));
}
, but that's why I don't know the ? in Func<?, T> above. This one for example needs ? to be two parameters. Could it be passed in as object somehow? I have a feeling it could be possible, but if so it needs some real reflection magic.
You can use Expression:
static Task<T> TaskFromEventHelper<T>(object target, string eventName, Delegate resultSetter)
{
var tcs = new TaskCompletionSource<T>();
var addMethod = target.GetType().GetEvent(eventName).GetAddMethod();
var delegateType = addMethod.GetParameters()[0].ParameterType;
var methodInfo = delegateType.GetMethod("Invoke");
var parameters = methodInfo.GetParameters()
.Select(a => Expression.Parameter(a.ParameterType))
.ToArray();
// building method, which argument count and
// their types are not known at compile time
var exp = // (%arguments%) => tcs.SetResult(resultSetter.Invoke(%arguments%))
Expression.Lambda(
delegateType,
Expression.Call(
Expression.Constant(tcs),
tcs.GetType().GetMethod("SetResult"),
Expression.Call(
Expression.Constant(resultSetter),
resultSetter.GetType().GetMethod("Invoke"),
parameters)),
parameters);
addMethod.Invoke(target, new object[] { exp.Compile() });
return tcs.Task;
}

Passing a method call and its parameter to a different method

I am using an external automation library with bunch of APIs with either 1 or 2 parameters which randomly throws TargetInvocationException. Calling these APIs second or third time usually works. I therefore created two helper methods to encapsulate the multiple retry logic
//Original API calls
bool result1 = Foo1(true);
int result2 = Foo2(4, "abc");
//New API calls
bool result1 = SafeMethodCall(Foo1, true);
int result2 = SafeMethodCall(Foo2, 4, "abc");
//Helper Methods
public static TResult SafeMethodCall<T, TResult>(
Func<T, TResult> unSafeMethod,
T parameter)
{
int numberOfMethodInvocationAttempts = 3;
int sleepIntervalBetweenMethodInvocations = 10000;
for (int i = 0; i < numberOfMethodInvocationAttempts; i++)
{
try
{
return unSafeMethod(parameter);
}
catch (System.Reflection.TargetInvocationException ex)
{
System.Threading.Thread.Sleep(sleepIntervalBetweenMethodInvocations);
}
}
}
public static TResult SafeTargetInvocationMethodCall<T1, T2, TResult>(
Func<T1, T2, TResult> unSafeMethod,
T1 parameter1,
T2 parameter2)
{
int numberOfMethodInvocationAttempts = 3;
int sleepIntervalBetweenMethodInvocations = 10000;
for (int i = 0; i < numberOfMethodInvocationAttempts; i++)
{
try
{
return unSafeMethod(parameter1, parameter2);
}
catch (System.Reflection.TargetInvocationException ex)
{
System.Threading.Thread.Sleep(sleepIntervalBetweenMethodInvocations);
}
}
}
Problem: If you see the two helper methods above have the same body and the only difference is unsafeMethod call inside the try block. How can I avoid code duplication here as I might have to add a overloaded method that accepts
Func<TResult>
as another parameter type.
Just pass in Func<TResult> and call it like this:
bool result1 = SafeMethodCall(() => Foo1(true));
int result2 = SafeMethodCall(() => Foo2(4, "abc"));
In other words, encapsulate the arguments in the delegate itself.

Categories

Resources