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[]>();
});
}
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 code to insert and update entities, but the logic are very similar: instance a controller, validate de request, if error, resturns Failed, else execute the operation.
/// <summary>
/// Method Add with similar code in Update method
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public PersonResponse Add(PersonInsertRequest item)
{
var result = new PersonResponse();
var controller = new PersonController(classmates);
result.Messages = controller.ValidateInsert(item);
if (result.Messages != null && result.Messages.Any())
{
result.Status = "failed";
}
else
{
result = controller.ExecuteInsert(item);
}
return result;
}
/// <summary>
/// Method Update with similar code in Add method
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public PersonResponse Update(PersonUpdateRequest item)
{
var result = new PersonResponse();
var controller = new PersonController(classmates);
result.Messages = controller.ValidateUpdate(item);
if (result.Messages != null && result.Messages.Any())
{
result.Status = "failed";
}
else
{
result = controller.ExecuteUpdate(item);
}
return result;
}
-
I have tried to use delegates, but I can't use them, because I cannot assign a delegate to controller.ValidateInsert(item);
public class BaseLogic
{
public delegate List<Message> Validator(BaseRequest request);
public delegate BaseResponse Executor(BaseRequest request);
public BaseResponse Execute(BaseRequest request, Validator funcValidator, Executor funcExecutor)
{
var result = new BaseResponse();
result.Messages = funcValidator(request);
if (result.Messages != null && result.Messages.Any())
{
result.Status = "failed";
}
else
{
result = funcExecutor(request);
}
return result;
}
}
I want to reduce Add method and Update method in another more generic.
using System;
using System.Collections.Generic;
using System.Linq;
class Test
{
private object classmates;
public PersonResponse Add(PersonInsertRequest item)
{
var controller = new PersonController(classmates);
return ValidateAndExecute(() => controller.ValidateInsert(item),
() => controller.ExecuteInsert(item));
}
public PersonResponse Update(PersonUpdateRequest item)
{
var controller = new PersonController(classmates);
return ValidateAndExecute(() => controller.ValidateUpdate(item),
() => controller.ExecuteUpdate(item));
}
private PersonResponse ValidateAndExecute(Func<IEnumerable<string>> validator,
Func<PersonResponse> execute)
{
var result = new PersonResponse();
result.Messages = validator();
if (result.Messages != null && result.Messages.Any())
{
result.Status = "failed";
}
else
{
result = execute();
}
return result;
}
}
With my generic method in my base class, I can refactorize my methods
/// <summary>
/// Method Add with similar code in Update method
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public PersonResponse Add(PersonInsertRequest item)
{
var controller = new PersonController(classmates);
Validator myValidator = request => controller.ValidateInsert((PersonInsertRequest)request);
Executor myExecutor = request => controller.ExecuteInsert((PersonInsertRequest)request);
var result = Execute(item, myValidator, myExecutor);
return result as PersonResponse;
}
/// <summary>
/// Method Update with similar code in Add method
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public PersonResponse Update(PersonUpdateRequest item)
{
var controller = new PersonController(classmates);
Validator myValidator = request => controller.ValidateUpdate((PersonUpdateRequest)request);
Executor myExecutor = request => controller.ExecuteUpdate((PersonUpdateRequest)request);
var result = Execute(item, myValidator, myExecutor);
return result as PersonResponse;
}
I have a Silverlight 5 browser application.
There is a class
public class ActivityControl:UserControl {
public void LoadSubControls() {
//Creates Other UserControls, does calculations and is very slow..No refactoring..
}
}
I need to create multiple instances of this class and call the method LoadSubControls on runtime.
public class BasicContainer:UserControl {
public void CreateMultipleActivityControls() {
for (int i = 0; i < 1000; i++) {
ActivityControl c = new ActivityControl(); ====> I need to call this in a different thread but causes Invalid Cross Thread Exception
c.LoadSubControls();
}
}
}
Is there any way to create multiple UI Threads in order to avoid invalid cross thread exception?
I need multithreading for performance reasons and because the method call is very slow and the UI freezes.
Is there any way to call method SetSyncronizationContext (which is [SecurityCritical]) in Silverlight?
There is no avoiding creating these controls on the UI thread, but you could take advantage of System.Threading.Tasks.Task from Task Parallel Library (TPL) to allow for asynchronous operations.
I've been able to do something like this in silverlight 5 with a structure like this. Got the original idea looking at the source for Caliburn.Micro.
The following is a subset that applies to what you want.
public interface IPlatformProvider {
/// <summary>
/// Executes the action on the UI thread asynchronously.
/// </summary>
/// <param name = "action">The action to execute.</param>
System.Threading.Tasks.Task OnUIThreadAsync(Action action);
}
Here is the implementation.
/// <summary>
/// A <see cref="IPlatformProvider"/> implementation for the XAML platfrom (Silverlight).
/// </summary>
public class XamlPlatformProvider : IPlatformProvider {
private Dispatcher dispatcher;
public XamlPlatformProvider() {
dispatcher = System.Windows.Deployment.Current.Dispatcher;
}
private void validateDispatcher() {
if (dispatcher == null)
throw new InvalidOperationException("Not initialized with dispatcher.");
}
/// <summary>
/// Executes the action on the UI thread asynchronously.
/// </summary>
/// <param name = "action">The action to execute.</param>
public Task OnUIThreadAsync(System.Action action) {
validateDispatcher();
var taskSource = new TaskCompletionSource<object>();
System.Action method = () => {
try {
action();
taskSource.SetResult(null);
} catch (Exception ex) {
taskSource.SetException(ex);
}
};
dispatcher.BeginInvoke(method);
return taskSource.Task;
}
}
You could either go down the constructor DI route to pass in the provider or use a static locator pattern like this.
/// <summary>
/// Access the current <see cref="IPlatformProvider"/>.
/// </summary>
public static class PlatformProvider {
private static IPlatformProvider current = new XamlPlatformProvider();
/// <summary>
/// Gets or sets the current <see cref="IPlatformProvider"/>.
/// </summary>
public static IPlatformProvider Current {
get { return current; }
set { current = value; }
}
}
Now you should be able to make your calls without blocking the main thread and freezing the UI
public class BasicContainer : UserControl {
public async Task CreateMultipleActivityControls() {
var platform = PlatformProvider.Current;
for (var i = 0; i < 1000; i++) {
await platform.OnUIThreadAsync(() => {
var c = new ActivityControl();
c.LoadSubControls();
});
}
}
}
if making multiple calls to the dispatcher caused any performance issues you could instead move the entire process to one acync call.
public class BasicContainer : UserControl {
public async Task CreateMultipleActivityControls() {
var platform = PlatformProvider.Current;
await platform.OnUIThreadAsync(() => {
for (var i = 0; i < 1000; i++) {
var c = new ActivityControl();
c.LoadSubControls();
}
});
}
}
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.