I created an IDisposable object that log the execution time on Dispose.
Then, I created a RealProxy that uses this object to log the time of any method call of my business class
My business class uses async methods, which then leave the using statement before completion of the task, and then log wrong execution time.
Here's my code:
/// <summary>
/// Logging proxy with stopwatch
/// </summary>
/// <typeparam name="T"></typeparam>
public sealed class LoggingProxy<T> : RealProxy// where T : MarshalByRefObject
{
private ILog _logger;
private readonly T _instance;
private LoggingProxy(T instance, ILog logger)
: base(typeof(T))
{
_logger = logger;
_instance = instance;
}
/// <summary>
/// Create the Transparent proy for T
/// </summary>
/// <param name="type">An implementation type of T</param>
/// <returns>T instance</returns>
public static T Create(ILog logger)
{
logger.DebugFormat("[{0}] Instantiate {1}", "LoggingProxy", typeof(T).Name);
var instance = (T)Activator.CreateInstance(typeof(T), logger);
//return the proxy with execution timing if debug enable in logger
if (logger.IsDebugEnabled)
return (T)new LoggingProxy<T>(instance, logger).GetTransparentProxy();
else
return instance;
}
/// <summary>
/// Invoke the logging method using Stopwatch to log execution time
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
public override IMessage Invoke(IMessage msg)
{
var methodCall = (IMethodCallMessage)msg;
var method = (MethodInfo)methodCall.MethodBase;
string methodName = method.Name;
string className = method.DeclaringType.Name;
//return directly methods inherited from Object
if (method.DeclaringType.Name.Equals("Object"))
{
var result = method.Invoke(_instance, methodCall.Args);
return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall);
}
using (var logContext = _logger.DebugTiming("[{0}] Execution time for {1}", className, methodName))
{
_logger.DebugFormat("[{0}] Call method {1}", className, methodName);
//execute the method
//var result = method.Invoke(_instance, methodCall.Args);
object[] arg = methodCall.Args.Clone() as object[];
var result = method.Invoke(_instance, arg);
//wait the task ends before log the timing
if (result is Task)
(result as Task).Wait();
return new ReturnMessage(result, arg, 0, methodCall.LogicalCallContext, methodCall);
}
}
The _logger.DebugTiming method start a stopwatch tand log it on Dispose.
The only way I found to make it work with async methods, is to use that line:
//wait the task ends before log the timing
if (result is Task)
(result as Task).Wait();
But I just have the feeling that I break all the benefits of async methods by doing that.
-> If you have a suggestion about how to make a proper implementation
-> Any idea of the real impact of calling wait() on the proxy?
You can use Task.ContinueWith():
public override IMessage Invoke(IMessage msg)
{
var methodCall = (IMethodCallMessage)msg;
var method = (MethodInfo)methodCall.MethodBase;
string methodName = method.Name;
string className = method.DeclaringType.Name;
//return directly methods inherited from Object
if (method.DeclaringType.Name.Equals("Object"))
{
var result = method.Invoke(_instance, methodCall.Args);
return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall);
}
var logContext = _logger.DebugTiming("[{0}] Execution time for {1}", className, methodName);
bool disposeLogContext = true;
try
{
_logger.DebugFormat("[{0}] Call method {1}", className, methodName);
//execute the method
//var result = method.Invoke(_instance, methodCall.Args);
object[] arg = methodCall.Args.Clone() as object[];
var result = method.Invoke(_instance, arg);
//wait the task ends before log the timing
if (result is Task) {
disposeLogContext = false;
((Task)result).ContinueWith(() => logContext.Dispose());
}
return new ReturnMessage(result, arg, 0, methodCall.LogicalCallContext, methodCall);
}
finally
{
if (disposeLogContext)
logContext.Dispose();
}
}
Don't call Wait() on the task - that changes the behavior and might lead to deadlocks.
Related
As of now, the following code calls the Tick?.Invoke method every second. Is there a way to easily change the code so that it gets called every 5 seconds for example?
private void Timer()
{
var now = DateTime.Now;
int lastSecond = now.Second;
int lastDay = now.Day;
while (goOnTiming)
{
now = DateTime.Now;
if (now.Second != lastSecond)
{
Tick?.Invoke(this, new TickEventArgs(now: now));
lastSecond = now.Second;
}
if (lastDay != now.Day)
{
NewDay?.Invoke(this, new TickEventArgs(now: now));
lastDay = now.Day;
}
}
}
You could use a builtin timer class, there are various.
You could also use my base class for an async ticker:
/// <summary>
/// Base class for an async ticker (runs a function every period or 'tick')
/// Adapted from <see href="https://stackoverflow.com/a/62724908/4122889"/>
/// NOTE this class was not designed to handle UI in any way - it could, but test beforehand!
/// </summary>
public abstract class TickerBase
{
#region Properties and Fields
private readonly ILogger<TickerBase> _logger;
public TimeSpan Interval { get; protected set; }
private readonly Action<ILogger, string, Exception> _tickerStarted = LoggerMessage.Define<string>(LogLevel.Trace, new EventId(0, nameof(_tickerStarted)), "Starting ticker: {0}");
private readonly Action<ILogger, string, Exception> _tickerCancelled = LoggerMessage.Define<string>(LogLevel.Trace, new EventId(0, nameof(_tickerCancelled)), "Cancellation requested: {0}");
#endregion
#region Construction and Destruction
protected TickerBase(ILoggerFactory loggerFactory, TimeSpan interval)
{
if(interval == default) throw new ArgumentOutOfRangeException(nameof(interval), "Interval was its default value");
_logger = loggerFactory.CreateLogger<TickerBase>() ?? throw new ArgumentNullException(nameof(loggerFactory));
Interval = interval;
}
#endregion
#region Starting
/// <summary>
/// Start the ticker. Don't await this function, it will run indefinitely.
/// Be mindful of exceptions.
/// Calling this function more than once will start more tasks and thus more tickers.
/// </summary>
/// <param name="ctx">cancellation token to cancel the timer</param>
/// <returns></returns>
public async Task StartAsync(CancellationToken ctx = default)
{
// Log starting and stopping of ticker(s)
_tickerStarted(_logger, GetType().Name, null);
ctx.Register(() => _tickerCancelled(_logger, GetType().Name, null));
while (true)
{
var delayTask = Task.Delay(Interval, ctx);
await OnTickAsync(ctx)
.ConfigureAwait(false);
await delayTask
.ConfigureAwait(false);
ctx.ThrowIfCancellationRequested();
}
// ReSharper disable once FunctionNeverReturns Reason: as designed
}
protected abstract Task OnTickAsync(CancellationToken ctx = default);
}
#endregion
}
Use timers, you can use system timers or form timers. Below an example of a system timer:
private void CreateTimer()
{
var timer = new System.Threading.Timer(timerCallback);
timer.Change(0, 5000);
}
private void timerCallback(object state)
{
System.Console.WriteLine("The timer called me");
}
BTW probably you take a lot of CPU with your approach.
This is probably not possible, but the OCD in me wants to at least ask if there is a way :)
I have this method:
public async Task<List<Strategy>> Handle(StrategyList query, CancellationToken cancellationToken)
{
return _attemptHandler.List();
}
I have now added some Attempts to help with error handling, so my code changed to this:
public async Task<Attempt<List<Strategy>>> Handle(StrategyList query, CancellationToken cancellationToken)
{
var attempt = _attemptHandler.List();
if (attempt.Failed) return attempt.Error;
return attempt.Result.ToList();
}
Think of an Attempt like an IdentityResult.
What I would like to do, so completely remove the 2nd line so it becomes something like this:
public async Task<Attempt<List<Strategy>>> Handle(StrategyList query, CancellationToken cancellationToken)
{
var attempt = _attemptHandler.List().ThrowIfError();
return attempt.Result.ToList();
}
So basically, if there was an error trying to get the list, then return that error (in the method ThrowIfError) but if there isn't, continue on to the return attempt.Result.ToList().
Is this possible?
You might be asking why. This use case I gave there doesn't look like a lot, but there are some places where I have to check multiple attempts and I would like it if I could do it without having to write the same code over and over (i.e. if (attempt.Failed) return attempt.Error;)
Here is an example of multiple attempts:
public async Task<Attempt<Strategy>> Handle(StrategySave query, CancellationToken cancellationToken)
{
var request = query.Model;
_strategyValidator.Validate(request);
if (request.Id == 0)
{
var attempt = _attemptHandler.Create(request);
if (attempt.Failed) return attempt.Error;
}
else
{
var attempt = _attemptHandler.List();
if (attempt.Failed) return attempt.Error;
var strategy = attempt.Result.ToList().SingleOrDefault(m => m.Id.Equals(query.Model.Id));
if (strategy == null) return new NotFoundError(nameof(Strategy), query.Model.Id.ToString());
strategy.Url = request.Url;
var updateAttempt = _attemptHandler.Update(strategy);
if (updateAttempt.Failed) return updateAttempt.Error;
}
var saveAttempt = await _attemptHandler.SaveChangesAsync();
if (saveAttempt.Failed) return saveAttempt.Error;
return request;
}
Here is:
a simple implementation of an Attempt<TResult> class that lets you do what you want to achieve and
a unit test that demonstrates how it is used.
To simplify, the example uses a List<string> as the result type. The HandleAsync method corresponds to your Handle method. MakeAttemptAsync() is comparable to your attemptHandler.List().
/// <summary>
/// Utility class that helps shorten the calling code.
/// </summary>
public static class Attempt
{
public static async Task<Attempt<TResult>> ResultAsync<TResult>(Task<TResult> task)
{
return await Attempt<TResult>.ResultAsync(task);
}
public static Attempt<TResult> ResultOf<TResult>(Func<TResult> func)
{
return Attempt<TResult>.ResultOf(func);
}
}
/// <summary>
/// Represents a successful or failed attempt.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
public class Attempt<TResult>
{
private Attempt(TResult result, bool success, Exception exception)
{
Result = result;
Success = success;
Exception = exception;
}
public TResult Result { get; }
public bool Success { get; }
public Exception Exception { get; }
public static async Task<Attempt<TResult>> ResultAsync(Task<TResult> task)
{
try
{
TResult result = await task;
return new Attempt<TResult>(result, true, null);
}
catch (Exception ex)
{
return new Attempt<TResult>(default, false, ex);
}
}
public static Attempt<TResult> ResultOf(Func<TResult> func)
{
try
{
TResult result = func();
return new Attempt<TResult>(result, true, null);
}
catch (Exception ex)
{
return new Attempt<TResult>(default, false, ex);
}
}
}
public class AttemptsTests
{
private static readonly List<string> SuccessList = new List<string> { "a", "b", "c" };
/// <summary>
/// Simple demonstrator for a short, synchronous handler making use of the
/// Attempt class, called with flag equal to true or false to simulate
/// success or failure of the MakeAttemptAsync method.
/// </summary>
private static Attempt<List<string>> Handle(bool flag)
{
return Attempt.ResultOf(() => MakeAttempt(flag));
}
/// <summary>
/// Simple demonstrator for a short, asynchronous handler making use of the
/// Attempt class, called with flag equal to true or false to simulate
/// success or failure of the MakeAttemptAsync method.
/// </summary>
private static async Task<Attempt<List<string>>> HandleAsync(bool flag)
{
Task<List<string>> task = MakeAttemptAsync(flag);
return await Attempt.ResultAsync(task);
}
/// <summary>
/// Simple dummy method that returns a List or throws an exception.
/// </summary>
private static List<string> MakeAttempt(bool flag)
{
return flag
? SuccessList
: throw new Exception("Failed attempt");
}
/// <summary>
/// Simple dummy method that returns a successful or failed task.
/// </summary>
private static Task<List<string>> MakeAttemptAsync(bool flag)
{
return flag
? Task.FromResult(SuccessList)
: Task.FromException<List<string>>(new Exception("Failed attempt"));
}
[Fact]
public void Handle_Failure_ExceptionReturned()
{
Attempt<List<string>> attempt = Handle(false);
Assert.False(attempt.Success);
Assert.Null(attempt.Result);
Assert.Equal("Failed attempt", attempt.Exception.Message);
}
[Fact]
public void Handle_Success_ListReturned()
{
Attempt<List<string>> attempt = Handle(true);
Assert.True(attempt.Success);
Assert.Equal(SuccessList, attempt.Result);
Assert.Null(attempt.Exception);
}
[Fact]
public async Task HandleAsync_Failure_ExceptionReturned()
{
Attempt<List<string>> attempt = await HandleAsync(false);
Assert.False(attempt.Success);
Assert.Null(attempt.Result);
Assert.Equal("Failed attempt", attempt.Exception.Message);
}
[Fact]
public async Task HandleAsync_Success_ListReturned()
{
Attempt<List<string>> attempt = await HandleAsync(true);
Assert.True(attempt.Success);
Assert.Equal(SuccessList, attempt.Result);
Assert.Null(attempt.Exception);
}
}
Update 2020-01-26
I amended the above example by adding a new static Attempt utility class that helps shorten the calling code. For example, instead of writing:
return await Attempt<List<string>>.ResultAsync(task);
you can write:
return await Attempt.ResultAsync(task);
as TResult is implicit from the task parameter. Secondly, I added a ResutOf method that takes a Func<TResult>, so you don't need to use TaskFromResult to turn a synchronous result into a task.
You can check for "Rail Oriented Programming", which is exactly what you are trying to achieve.
For example with multiple attempts where next attempt should be executed only when previous one succeed.
public Attempt<List<Strategy>> Process(params AttemptHandler[] handlers)
{
var attempt = default(Attempt<List<Strategy>>);
foreach(var handler in handlers)
{
attempt = handler.List();
if (attempt.Failed)
{
return attempt.Error;
}
}
return attempt.Result.ToList();
}
Instead of using null as default value for attempt variable - use "empty" attempt object, which will return empty attempt if no handlers were provided.
Usage
var attempt = Process(_handler1, _handler2, _handler3);
I have a dictionary in a singleton class. I am saving there the pair , every time I access to that dictionary from the method that is creating the token it shows all the credentials that I've stored there.
But when I access from another class in another project of the solutions it displays the dictionary empty. Can anybody tell me why this happens?
This is the class that manage the dictionary:
public class UserAccessToken
{
public Dictionary<string, string> UserDictionary { get; set; }
private static UserAccessToken _instance;
private UserAccessToken() { }
public static UserAccessToken Instance
{
get
{
if (_instance == null)
_instance = new UserAccessToken
{
UserDictionary = new Dictionary<string, string>()
};
return _instance;
}
}
}
This is the method that insert the key,value pair in the dictionary:
public override Task TokenEndpointResponse(OAuthTokenEndpointResponseContext context)
{
var accessToken = context.AccessToken;
if (context.Properties.Dictionary.ContainsKey("userName"))
{
var username = context.Properties.Dictionary["userName"];
// If I access here multiple times the singleton works
UserAccessToken.Instance.UserDictionary[username] = accessToken;
}
return Task.FromResult<object>(null);
}
This is the method where I access the dictionary, from here I can see that it's empty:
private bool IsTokenValid(HttpContextBase httpContext)
{
var username = httpContext.User.Identity.Name;
var userTokens = UserAccessToken.Instance.UserDictionary;
var tokenToAccess = httpContext.Request.Headers["Authorization"];
tokenToAccess = tokenToAccess.Replace("Bearer ", "");
if (userTokens.ContainsKey(username))
{
var token = userTokens[username];
if (token == tokenToAccess) return true;
}
return true;
}
I already solved my problem, but I'll let my solution here in case could be useful for somebody.
The problem is that if you are running two different projects, that will mean two different process, so, what I wanted to do is pretty impossible. I used Redis for this and it is working well.
This is an example of Redis use:
public class CallManagerCache : ICallManagerMethods{
private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer
.Connect(CloudConfigurationManager.GetSetting("RedisConnectionString")));
public static ConnectionMultiplexer cacheConnection
{
get
{
return lazyConnection.Value;
}
}
/// <summary>
/// Here you save the value in cache, you get the connection, then StringSetAsync is in charge of saving the value
/// </summary>
/// <param name="name"></param>
/// <param name="template"></param>
public async Task UpdateCallInstance(int id, byte[] data, bool instanceForCallback = false, TimeSpan? timespan = null)
{
var cache = cacheConnection.GetDatabase();
await cache.StringSetAsync(instanceForCallback ? $"Call_{id}" : id.ToString(), data, timespan ?? new TimeSpan(0, 0, 15, 0));
}
/// <summary>
/// Here you get the value in cache, you get the connection, then StringGetAsync is in charge of getting the value
/// </summary>
/// <param name="name"></param>
/// <param name="template"></param>
public async Task<CallInstance> GetById(int id, bool isForCallback)
{
var cache = cacheConnection.GetDatabase();
var callInstance = new CallInstance
{
Id = id,
InstanceData = await cache.StringGetAsync(isForCallback ? $"Call_{id}" : id.ToString())
};
return callInstance;
}
}
I am working with code that currently does not use any dependency injection, and makes multiple service calls through a WCF client.
public class MyClass
{
public void Method()
{
try
{
ServiceClient client = new ServiceClient();
client.Operation1();
}
catch(Exception ex)
{
// Handle Exception
}
finally
{
client = null;
}
try
{
ServiceClient client = new ServiceClient();
client.Operation2();
}
catch(Exception ex)
{
// Handle Exception
}
finally
{
client = null;
}
}
}
My goal is to make this code unit-testable through the use of dependency injection. My first thought was to simply pass an instance of the service client to the class constructor. Then in my unit tests, I can create a mock client for testing purposes that does not make actual requests to the web service.
public class MyClass
{
IServiceClient client;
public MyClass(IServiceClient client)
{
this.client = client;
}
public void Method()
{
try
{
client.Operation1();
}
catch(Exception ex)
{
// Handle Exception
}
try
{
client.Operation2();
}
catch(Exception ex)
{
// Handle Exception
}
}
}
However, I realized that this changes the code in a way that affects its original behavior, based on the information from this question: Reuse a client class in WCF after it is faulted
In the original code, if the call to Operation1 fails and the client is put in a faulted state, a new instance of ServiceClient is created, and Operation2 will still be called.
In the updated code, if the call to Operation1 fails, the same client is reused to call Operation2, but this call will fail if the client is in a faulted state.
Is it possible to create a new instance of the client while keeping the dependency injection pattern? I realize that reflection can be used to instantiate a class from a string, but I feel like reflection isn't the right way to go about this.
You need to inject factory rather than instance itself:
public class ServiceClientFactory : IServiceClientFactory
{
public IServiceClient CreateInstance()
{
return new ServiceClient();
}
}
Then in MyClass you simply use factory to get instance each time it is required:
// Injection
public MyClass(IServiceClientFactory serviceClientFactory)
{
this.serviceClientFactory = serviceClientFactory;
}
// Usage
try
{
var client = serviceClientFactory.CreateInstance();
client.Operation1();
}
Alternatively, you can inject function returning such client using Func<IServiceClient> delegate so that you can avoid creating extra class and interface:
// Injection
public MyClass(Func<IServiceClient> createServiceClient)
{
this.createServiceClient = createServiceClient;
}
// Usage
try
{
var client = createServiceClient();
client.Operation1();
}
// Instance creation
var myClass = new MyClass(() => new ServiceClient());
In your case Func<IServiceClient> should be sufficient. Once instance creation logic gets more complicated it would be a time reconsider explicitly implemented factory.
What I did in the past was have a generic client (with 'interception' using Unity) which creates a new connection from the ChannelFactory, based on the service's business interface, for each call and close that connection after each call, deciding on whether to indicate the connection is faulted based on whether an exception or normal response was returned. (See below.)
My real code using this client just requests an instance implementing the business interface and it will get an instance of this generic wrapper. The instance returned does not need to be disposed of, or treated differently based on whether an exception was returned. To get a service client (using the wrapper below) my code does: var client = SoapClientInterceptorBehavior<T>.CreateInstance(new ChannelFactory<T>("*")), which is usually hidden in a registry or passed in as a constructor argument. So in your case I would end up with var myClass = new MyClass(SoapClientInterceptorBehavior<IServiceClient>.CreateInstance(new ChannelFactory<IServiceClient>("*"))); (you probably want to put the whole call to create the instance in some factory method of your own, just requiring IServiceClient as input type, to make it a bit more readable. ;-))
In my tests I can just injected a mocked implementation of the service and test whether the right business methods were called and their results properly handled.
/// <summary>
/// IInterceptionBehavior that will request a new channel from a ChannelFactory for each call,
/// and close (or abort) it after each call.
/// </summary>
/// <typeparam name="T">business interface of SOAP service to call</typeparam>
public class SoapClientInterceptorBehavior<T> : IInterceptionBehavior
{
// create a logger to include the interface name, so we can configure log level per interface
// Warn only logs exceptions (with arguments)
// Info can be enabled to get overview (and only arguments on exception),
// Debug always provides arguments and Trace also provides return value
private static readonly Logger Logger = LogManager.GetLogger(LoggerName());
private static string LoggerName()
{
string baseName = MethodBase.GetCurrentMethod().DeclaringType.FullName;
baseName = baseName.Remove(baseName.IndexOf('`'));
return baseName + "." + typeof(T).Name;
}
private readonly Func<T> _clientCreator;
/// <summary>
/// Creates new, using channelFactory.CreatChannel to create a channel to the SOAP service.
/// </summary>
/// <param name="channelFactory">channelfactory to obtain connections from</param>
public SoapClientInterceptorBehavior(ChannelFactory<T> channelFactory)
: this(channelFactory.CreateChannel)
{
}
/// <summary>
/// Creates new, using the supplied method to obtain a connection per call.
/// </summary>
/// <param name="clientCreationFunc">delegate to obtain client connection from</param>
public SoapClientInterceptorBehavior(Func<T> clientCreationFunc)
{
_clientCreator = clientCreationFunc;
}
/// <summary>
/// Intercepts calls to SOAP service, ensuring proper creation and closing of communication
/// channel.
/// </summary>
/// <param name="input">invocation being intercepted.</param>
/// <param name="getNext">next interceptor in chain (will not be called)</param>
/// <returns>result from SOAP call</returns>
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Logger.Info(() => "Invoking method: " + input.MethodBase.Name + "()");
// we will not invoke an actual target, or call next interception behaviors, instead we will
// create a new client, call it, close it if it is a channel, and return its
// return value.
T client = _clientCreator.Invoke();
Logger.Trace(() => "Created client");
var channel = client as IClientChannel;
IMethodReturn result;
int size = input.Arguments.Count;
var args = new object[size];
for(int i = 0; i < size; i++)
{
args[i] = input.Arguments[i];
}
Logger.Trace(() => "Arguments: " + string.Join(", ", args));
try
{
object val = input.MethodBase.Invoke(client, args);
if (Logger.IsTraceEnabled)
{
Logger.Trace(() => "Completed " + input.MethodBase.Name + "(" + string.Join(", ", args) + ") return-value: " + val);
}
else if (Logger.IsDebugEnabled)
{
Logger.Debug(() => "Completed " + input.MethodBase.Name + "(" + string.Join(", ", args) + ")");
}
else
{
Logger.Info(() => "Completed " + input.MethodBase.Name + "()");
}
result = input.CreateMethodReturn(val, args);
if (channel != null)
{
Logger.Trace("Closing channel");
channel.Close();
}
}
catch (TargetInvocationException tie)
{
// remove extra layer of exception added by reflective usage
result = HandleException(input, args, tie.InnerException, channel);
}
catch (Exception e)
{
result = HandleException(input, args, e, channel);
}
return result;
}
private static IMethodReturn HandleException(IMethodInvocation input, object[] args, Exception e, IClientChannel channel)
{
if (Logger.IsWarnEnabled)
{
// we log at Warn, caller might handle this without need to log
string msg = string.Format("Exception from " + input.MethodBase.Name + "(" + string.Join(", ", args) + ")");
Logger.Warn(msg, e);
}
IMethodReturn result = input.CreateExceptionMethodReturn(e);
if (channel != null)
{
Logger.Trace("Aborting channel");
channel.Abort();
}
return result;
}
/// <summary>
/// Returns the interfaces required by the behavior for the objects it intercepts.
/// </summary>
/// <returns>
/// The required interfaces.
/// </returns>
public IEnumerable<Type> GetRequiredInterfaces()
{
return new [] { typeof(T) };
}
/// <summary>
/// Returns a flag indicating if this behavior will actually do anything when invoked.
/// </summary>
/// <remarks>
/// This is used to optimize interception. If the behaviors won't actually
/// do anything (for example, PIAB where no policies match) then the interception
/// mechanism can be skipped completely.
/// </remarks>
public bool WillExecute
{
get { return true; }
}
/// <summary>
/// Creates new client, that will obtain a fresh connection before each call
/// and closes the channel after each call.
/// </summary>
/// <param name="factory">channel factory to connect to service</param>
/// <returns>instance which will have SoapClientInterceptorBehavior applied</returns>
public static T CreateInstance(ChannelFactory<T> factory)
{
IInterceptionBehavior behavior = new SoapClientInterceptorBehavior<T>(factory);
return (T)Intercept.ThroughProxy<IMy>(
new MyClass(),
new InterfaceInterceptor(),
new[] { behavior });
}
/// <summary>
/// Dummy class to use as target (which will never be called, as this behavior will not delegate to it).
/// Unity Interception does not allow ONLY interceptor, it needs a target instance
/// which must implement at least one public interface.
/// </summary>
public class MyClass : IMy
{
}
/// <summary>
/// Public interface for dummy target.
/// Unity Interception does not allow ONLY interceptor, it needs a target instance
/// which must implement at least one public interface.
/// </summary>
public interface IMy
{
}
}
Using the command pattern returning tasks that are just sleeps for 5 seconds the total for the 3 tasks to complete is ~15 seconds.
What am I doing that is keeping this code from executing in "parallel"?
The calling code
var timer = new Stopwatch();
timer.Start();
var task = CommandExecutor.ExecuteCommand(new Fake());
var task2 = CommandExecutor.ExecuteCommand(new Fake());
var task3 = CommandExecutor.ExecuteCommand(new Fake());
Task.WaitAll(new Task[]
{
task, task2, task3
});
timer.Stop();
Debug.Print("{0}ms for {1},{2},{3} records", timer.ElapsedMilliseconds, task.Result.Count, task2.Result.Count(), task3.Result.Count());
The Commands being executed
public class Fake : Command<Task<Dictionary<string, string[]>>>
{
public override string ToString()
{
return string.Format("Fake");
}
protected override void Execute()
{
new System.Threading.ManualResetEvent(false).WaitOne(5000);
Result = Task.Factory.StartNew(() => new Dictionary<string, string[]>());
}
}
The Command Abstraction
public abstract class Command
{
public void Run()
{
try
{
var timer = new Stopwatch();
timer.Start();
//Debug.Print("{0}-{1}", ToString(), "Executing");
Execute();
timer.Stop();
Debug.Print("{0}-{1} Duration: {2}ms", ToString(), "Done", timer.ElapsedMilliseconds.ToString(CultureInfo.InvariantCulture));
}
catch (Exception ex)
{
Debug.Print("Error processing task:" + ToString(), ex);
}
}
public abstract override string ToString();
protected abstract void Execute();
}
/// <summary>
/// A command with a return value
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class Command<T> : Command
{
public T Result { get; protected set; }
public T GetResult()
{
Run();
return Result;
}
}
the Command Executor
public class CommandExecutor
{
/// <summary>
/// Executes the command.
/// </summary>
/// <param name="cmd">The CMD.</param>
public static void ExecuteCommand(Command cmd)
{
cmd.Run();
}
/// <summary>
/// Executes the command for commands with a result.
/// </summary>
/// <typeparam name="TResult">The type of the result.</typeparam>
/// <param name="cmd">The CMD.</param>
/// <returns></returns>
public static TResult ExecuteCommand<TResult>(Command<TResult> cmd)
{
ExecuteCommand((Command) cmd);
return cmd.Result;
}
The problem is that you aren't waiting inside the actual Task object, you're waiting in the method that creates the task before it actually provides that task:
protected override void Execute()
{
new System.Threading.ManualResetEvent(false).WaitOne(5000);
Result = Task.Factory.StartNew(() => new Dictionary<string, string[]>());
}
should instead be:
protected override void Execute()
{
Result = Task.Factory.StartNew(() =>
{
new System.Threading.ManualResetEvent(false).WaitOne(5000);
return new Dictionary<string, string[]>();
});
}