I have an Action-based UndoRedoTransactionManager that looks something like this:
public interface IUndoRedoTransactionManager
{
bool CanDo { get; }
bool CanUndo { get; }
void ClearHistory();
bool Do(Action doAction, Action undoAction, string description);
bool Redo();
void RedoAll();
bool Undo();
void UndoAll();
}
which is used throughout my codebase like this:
var done = false;
_manager.Do(() =>
{
Thread.Sleep(100);
SomeUiWork();
done = true;
}, () =>
{
Thread.Sleep(100);
UndoSomeUiWork();
done = false;
}, "Description");
I am working on some new code in which I want to use my UndoRedoTransactionManager like this:
var done = false;
_manager.Do(async () =>
{
await Task.Delay(100);
SomeUiWork();
done = true;
}, async () =>
{
await Task.Delay(100);
UndoSomeUiWork();
done = false;
}, "Description");
From what I understand, this new code creates async voids which should be avoided when possible. It also wouldn't guarantee that it runs without blocking.
I've read a bunch of blogs but I couldn't understand them well-enough to convert their information to my situation (I am new to async programming, and am probably doing a lot of things wrong).
My question is: How can I expand my Action-based UndoRedoTransactionManager to also support async/await? or How can I best tackle my issue?
I noticed that I could add a new method to my interface:
Task<bool> Do(Func<Task> action, Func<Task> undoAction, string description);
And the compiler will automatically pick this one when using async lambdas (and tell me to await it), however I then run into interchangeability issues.
My full UndoRedoTransactionManager implementation:
public class UndoRedoTransactionManager : IUndoRedoTransactionManager
{
private readonly Stack<UndoRedoTransaction> _done = new Stack<UndoRedoTransaction>();
private readonly Stack<UndoRedoTransaction> _unDone = new Stack<UndoRedoTransaction>();
public bool CanDo => _unDone.Count > 0;
public bool CanUndo => _done.Count > 0;
public void ClearHistory()
{
_done.Clear();
_unDone.Clear();
}
public bool Do(Action action, Action undoAction, string description)
{
var trans = new UndoRedoTransaction(action, undoAction, description);
_unDone.Clear();
trans.Do();
_done.Push(trans);
return true;
}
public bool Redo()
{
if (_unDone.Count == 0) return false;
var act = _unDone.Pop();
act.Do();
_done.Push(act);
return true;
}
public void RedoAll()
{
while (Redo())
{
}
}
public bool Undo()
{
if (_done.Count == 0) return false;
var act = _done.Pop();
act.Undo();
_unDone.Push(act);
return true;
}
public void UndoAll()
{
while (Undo())
{
}
}
private class UndoRedoTransaction
{
private readonly Action _doAction;
private readonly Action _undoAction;
public string Description { get; }
public UndoRedoTransaction(Action doAction, Action undoAction, string description)
{
_doAction = doAction;
_undoAction = undoAction;
Description = description;
}
public void Do()
{
_doAction();
}
public void Undo()
{
_undoAction();
}
}
}
Related
I'm trying to write a class that continuosly ping "in background" a list of one or more devices, and report the results to a Progress object in the GUI main class. Im very new with async/await and Tasks, but my code seems to work fine on my pc, even if i know its not so good designed. But when i start the application in a different computer it throws an InvalidOperationException from the Progress object because the Dictionary in is changed. I think it happens when i assign a new PingService to the same variable.
The PingService class starts pinging (SendPingAsync) a list of IP's on a function with a inf. loop that updates the PingServiceReply object for each iteration of the list and then "reporting" it to the Progress object.
What is the way for get it done, and what im doing wrong?
Here's the code.
PingSeviceReply class
public class PingServiceReply
{
private Dictionary<string, bool> ipDictionary;
internal PingServiceReply()
{
ipDictionary = new Dictionary<string, bool>();
}
public void SetIpStatus(string ip, bool status)
{
if (ipDictionary.ContainsKey(ip))
{
ipDictionary[ip] = status;
}
else
{
ipDictionary.Add(ip, status);
}
}
public Dictionary<string, bool> GetStatusDictionary()
{
return ipDictionary;
}
public bool AreAllOnline()
{
foreach (bool value in ipDictionary.Values)
{
if (!value)
{
return false;
}
}
return true;
}
}
PingService class
public class PingService
{
private string name;
private List<string> ipList;
private IProgress<PingServiceReply> progress;
private CancellationTokenSource cts;
private int timeout;
private Task tsk;
public PingService(string name, List<string> ipList, int timeoutInMillliseconds, IProgress<PingServiceReply> progress)
{
this.name = name;
this.ipList = ipList;
this.progress = progress;
this.timeout = timeoutInMillliseconds;
}
public PingService(string name, string ip, int timeoutInMillliseconds, IProgress<PingServiceReply> progress)
{
this.name = name;
this.ipList = new List<string>();
ipList.Add(ip);
this.progress = progress;
this.timeout = timeoutInMillliseconds;
}
public PingService()
{
cts = new CancellationTokenSource();
}
private async Task ContinuousPingAsync()
{
var ping = new System.Net.NetworkInformation.Ping();
PingReply singleResponse;
PingServiceReply ruleResponse = new PingServiceReply();
while (!cts.Token.IsCancellationRequested)
{
foreach (string ip in ipList)
{
singleResponse = await ping.SendPingAsync(ip, timeout).ConfigureAwait(false);
ruleResponse.SetIpStatus(ip, singleResponse.Status == IPStatus.Success);
}
progress.Report(ruleResponse);
}
}
public void StartService()
{
cts = new CancellationTokenSource();
tsk = ContinuousPingAsync();
}
public void StopService()
{
cts.Cancel();
}
public string GetName()
{
return name;
}
}
The progress object
IProgress<PingServiceReply> pingProgress = new Progress<PingServiceReply>(HandleSinglePing);
private void HandleSinglePing(PingServiceReply report)
{
if (report.AreAllOnline())
{
//online
}
else
{
//offline
}
}
How i use all in the gui class, on the combobox selectedItemChanged event
comboService.StopService();
comboService = new PingService("Combo", (string) comboBox.SelectedItem, 1000, pingProgress);
comboService.StartService();
I am trying to implement an entity framework configuration that deals with deadlocks and retries them. I already have a default execution strategy set in my MyConfiguration constructor. My question is, can I call one after the other, or will they override each other? I am not 100% confident with these so any information would be greatly appreciated.
If I use both in my MyConfiguration constructor, will they override each other or will they actually register both and therefore, both will work?
Here is the code:
public class MyConfiguration : DbConfiguration
{
public MyConfiguration()
{
// Trims all strings coming from entity framework
AddInterceptor(new StringTrimmerInterceptor());
SetExecutionStrategy("System.Data.SqlClient", () => SuspendExecutionStrategy
? (IDbExecutionStrategy)new DefaultExecutionStrategy()
: new SqlAzureExecutionStrategy());
SetExecutionStrategy("System.Data.SqlClient", () => new MyCustomExecutionStrategy(5, TimeSpan.FromSeconds(10)));
}
public static bool SuspendExecutionStrategy
{
get
{
return (bool?)CallContext.LogicalGetData("SuspendExecutionStrategy") ?? false;
}
set
{
CallContext.LogicalSetData("SuspendExecutionStrategy", value);
}
}
}
public class StringTrimmerInterceptor : IDbCommandTreeInterceptor
{
public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext)
{
if (interceptionContext.OriginalResult.DataSpace == DataSpace.SSpace)
{
var queryCommand = interceptionContext.Result as DbQueryCommandTree;
if (queryCommand != null)
{
var newQuery = queryCommand.Query.Accept(new StringTrimmerQueryVisitor());
interceptionContext.Result = new DbQueryCommandTree(
queryCommand.MetadataWorkspace,
queryCommand.DataSpace,
newQuery);
}
}
}
private class StringTrimmerQueryVisitor : DefaultExpressionVisitor
{
private static readonly string[] _typesToTrim = { "nvarchar", "varchar", "char", "nchar" };
public override DbExpression Visit(DbNewInstanceExpression expression)
{
var arguments = expression.Arguments.Select(a =>
{
var propertyArg = a as DbPropertyExpression;
if (propertyArg != null && _typesToTrim.Contains(propertyArg.Property.TypeUsage.EdmType.Name))
{
return EdmFunctions.Trim(a);
}
return a;
});
return DbExpressionBuilder.New(expression.ResultType, arguments);
}
}
}
public static class SqlRetryErrorCodes
{
public const int TimeoutExpired = -2;
public const int Deadlock = 1205;
public const int CouldNotOpenConnection = 53;
public const int TransportFail = 121;
}
public class MyCustomExecutionStrategy : DbExecutionStrategy
{
public MyCustomExecutionStrategy(int maxRetryCount, TimeSpan maxDelay) : base(maxRetryCount, maxDelay) { }
private readonly List<int> _errorCodesToRetry = new List<int>
{
SqlRetryErrorCodes.Deadlock,
SqlRetryErrorCodes.TimeoutExpired,
SqlRetryErrorCodes.CouldNotOpenConnection,
SqlRetryErrorCodes.TransportFail
};
protected override bool ShouldRetryOn(Exception exception)
{
var sqlException = exception as SqlException;
if (sqlException != null)
{
foreach (SqlError err in sqlException.Errors)
{
// Enumerate through all errors found in the exception.
if (_errorCodesToRetry.Contains(err.Number))
{
return true;
}
}
}
return false;
}
}
Looking at this post from a member of the .NET team it should override the strategy everytime you call it. The link shows that this can be changed during runtime even (on every ctor-call). In the usage section he states:
Now we can use the flag to disable retry logic for certain operations.
So my (unproved) answer is: You can call it more than one time and it will always have the last set strategy configured.
I'm developing an application for detecting motion within webcam frames.
For this, I'm using IBasicVideoEffect for extracting frames one by one from MediaCapture. I have created class CustomEffect which inherits IBasicVideoEffect. I have used OpenCV for motion detection, it is working fine. It is also giving me motion detection level. I want to raise event from CustomEffect if motion level is greater than threshold.
But for videoDefination code is:
var videoDefinition = new VideoEffectDefinition(typeof(CustomEffect).ToString());
Here for videoDefinition constructor it is asking for ClassID,
How can i get event from CustomEffect object.
I want to raise custom event from CustomEffect (eg.: MotionDetectedEvent )
Here is my CustomEffect class:
public sealed class CustomEffect : IBasicVideoEffect
{
private OpenCVHelper _helper;
private IPropertySet _configuration;
internal event EventHandler<EventArgs> MotionDetected;
public void SetProperties(IPropertySet configuration)
{
_configuration = configuration;
}
public void SetEncodingProperties(VideoEncodingProperties encodingProperties,
IDirect3DDevice device)
{
}
private bool IsToDetectMotion
{
get
{
object val;
if (_configuration != null &&
_configuration.TryGetValue("IsToDetectMotion", out val))
return (bool) val;
return false;
}
}
public void ProcessFrame(ProcessVideoFrameContext context)
{
var tempBitmap = context.OutputFrame.SoftwareBitmap;
context.InputFrame.SoftwareBitmap.CopyTo(tempBitmap);
var originalBitmap = SoftwareBitmap.Convert(tempBitmap, BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Straight);
var outputBitmap = new SoftwareBitmap(BitmapPixelFormat.Bgra8,
originalBitmap.PixelWidth, originalBitmap.PixelHeight,
BitmapAlphaMode.Straight);
if (!IsToDetectMotion)
{
context.InputFrame.SoftwareBitmap.CopyTo(context.OutputFrame.SoftwareBitmap);
return;
}
if (_helper == null)
_helper = new OpenCVHelper();
var level = _helper.MotionDetector(tempBitmap, outputBitmap);
RaiseMotionDetectedEvent();
Debug.WriteLine(level.ToString());
outputBitmap.CopyTo(context.OutputFrame.SoftwareBitmap);
}
private void RaiseMotionDetectedEvent()
{
if (MotionDetected != null)
MotionDetected(this, new EventArgs());
}
public void Close(MediaEffectClosedReason reason)
{
}
public void DiscardQueuedFrames()
{
}
public bool IsReadOnly { get; }
public IReadOnlyList<VideoEncodingProperties> SupportedEncodingProperties
{
get
{
var encodingProperties = new VideoEncodingProperties();
encodingProperties.Subtype = "ARGB32";
return new List<VideoEncodingProperties> {encodingProperties};
// If the list is empty, the encoding type will be ARGB32.
// return new List<VideoEncodingProperties>();
}
}
public MediaMemoryTypes SupportedMemoryTypes { get; }
public bool TimeIndependent { get; }
}
//in Windows Runtime Component
public sealed class FrameArgs
{
public FrameArgs(int frameCount)
{
FrameCount = frameCount;
}
public int FrameCount
{ get; }
}
public sealed partial class CustomEffect
{
#region ProcessFrameCompleted
public EventHandler<Object> ProcessFrameCompleted
{
get
{
object val;
if (configuration != null && configuration.TryGetValue(nameof(ProcessFrameCompleted), out val))
{
return (EventHandler<Object>)val;
}
return null;
}
}
public void RaiseProcessFrameCompleted(FrameArgs args)
{
ProcessFrameCompleted?.Invoke(null, (Object)args);
}
#endregion
//call as necessary
//RaiseProcessFrameCompleted(new FrameArgs(frameCount));
}
//in your app
public static async Task<IMediaExtension> AddCustomEffect(MediaCapture mediaCapture, EventHandler<FrameArgs> callBack)
{
if (mediaCapture == null)
{
throw new ArgumentException("Parameter cannot be null", nameof(mediaCapture));
}
var videoEffectDefinition =
// ReSharper disable once AssignNullToNotNullAttribute
new VideoEffectDefinition(typeof(CustomEffect).FullName);
var videoEffect =
await mediaCapture.AddVideoEffectAsync(videoEffectDefinition, MediaStreamType.VideoPreview);
videoEffect.SetProperties(
new PropertySet()
{
{
"ProcessFrameCompleted",
new EventHandler<object>((sender, e) =>
{
var args = (FrameArgs)e;
int frameCount = args.FrameCount;
callBack?.Invoke(sender, args);
})
}
});
return videoEffect;
}
I have a situation where I have multiple producers and multiple consumers. The producers enters a job into a queue. I chose the BlockingCollection and it works great since I need the consumers to wait for a job to be found. However, if I use the GetConsumingEnumerable() feature the order of the items in the collection change... this is not what I need.
It even says in MSDN http://msdn.microsoft.com/en-us/library/dd287186.aspx
that it does not preserve the order of the items.
Does anyone know an alternative for this situation?
I see that the Take method is available but does it also provide a 'wait' condition for the consumer threads?
It says http://msdn.microsoft.com/en-us/library/dd287085.aspx
'A call to Take may block until an item is available to be removed.' Is it better to use TryTake? I really need the thread to wait and keep checking for a job.
Take blocks the thread till something comes available.
TryTake as the name implies tries to do so but returns a bool if it fails or succeeds.
Allowing for more flex using it:
while(goingOn){
if( q.TryTake(out var){
Process(var)
}
else{
DoSomething_Usefull_OrNotUseFull_OrEvenSleep();
}
}
instead of
while(goingOn){
if( var x = q.Take(){
//w'll wait till this ever will happen and then we:
Process(var)
}
}
My votes are for TryTake :-)
EXAMPLE:
public class ProducerConsumer<T> {
public struct Message {
public T Data;
}
private readonly ThreadRunner _producer;
private readonly ThreadRunner _consumer;
public ProducerConsumer(Func<T> produce, Action<T> consume) {
var q = new BlockingCollection<Message>();
_producer = new Producer(produce,q);
_consumer = new Consumer(consume,q);
}
public void Start() {
_producer.Run();
_consumer.Run();
}
public void Stop() {
_producer.Stop();
_consumer.Stop();
}
private class Producer : ThreadRunner {
public Producer(Func<T> produce, BlockingCollection<Message> q) : base(q) {
_produce = produce;
}
private readonly Func<T> _produce;
public override void Worker() {
try {
while (KeepRunning) {
var item = _produce();
MessageQ.TryAdd(new Message{Data = item});
}
}
catch (ThreadInterruptedException) {
WasInterrupted = true;
}
}
}
public abstract class ThreadRunner {
protected readonly BlockingCollection<Message> MessageQ;
protected ThreadRunner(BlockingCollection<Message> q) {
MessageQ = q;
}
protected Thread Runner;
protected bool KeepRunning = true;
public bool WasInterrupted;
public abstract void Worker();
public void Run() {
Runner = new Thread(Worker);
Runner.Start();
}
public void Stop() {
KeepRunning = false;
Runner.Interrupt();
Runner.Join();
}
}
class Consumer : ThreadRunner {
private readonly Action<T> _consume;
public Consumer(Action<T> consume,BlockingCollection<Message> q) : base(q) {
_consume = consume;
}
public override void Worker() {
try {
while (KeepRunning) {
Message message;
if (MessageQ.TryTake(out message, TimeSpan.FromMilliseconds(100))) {
_consume(message.Data);
}
else {
//There's nothing in the Q so I have some spare time...
//Excellent moment to update my statisics or update some history to logfiles
//for now we sleep:
Thread.Sleep(TimeSpan.FromMilliseconds(100));
}
}
}
catch (ThreadInterruptedException) {
WasInterrupted = true;
}
}
}
}
}
USAGE:
[Fact]
public void ConsumerShouldConsume() {
var produced = 0;
var consumed = 0;
Func<int> produce = () => {
Thread.Sleep(TimeSpan.FromMilliseconds(100));
produced++;
return new Random(2).Next(1000);
};
Action<int> consume = c => { consumed++; };
var t = new ProducerConsumer<int>(produce, consume);
t.Start();
Thread.Sleep(TimeSpan.FromSeconds(5));
t.Stop();
Assert.InRange(produced,40,60);
Assert.InRange(consumed, 40, 60);
}
I've been trying to implement a fluent interface for a set of rules in my system. What I am trying to accomplish is this
TicketRules
.RequireValidation()
.When(quartType => quartType == QuartType.Before).TotalMilageIs(64)
.When(quartType => quartType == QuartType.After).TotalMilageIs(128);
However, I have trouble implementing the When conditional how I intended to be. Currently, I need to call When() twice like in this snippet:
rules.When(param => param.Remarque == "Test").TotalMilageIs(100);
rules.When(param => param.Remarque == "Other").TotalMilageIs(50);
var params1 = new AddTicketParameters() { Remarque = "Test" };
var params2 = new AddTicketParameters() { Remarque = "Other" };
rules.ExecuteWith(params1);
Assert.That(ticket.TotalMilage, Is.EqualTo(100));
rules.ExecuteWith(params2);
Assert.That(ticket.TotalMilage, Is.EqualTo(50));
My TicketRules class looks this:
[EditorBrowsable(EditorBrowsableState.Never)]
public class TicketRules : ITicketRule, IHideObjectMembers
{
private Ticket theTicket;
public Ticket Ticket
{
set
{
theTicket = value;
}
}
private List<ITicketRule> allRules = new List<ITicketRule>();
public TicketRules()
{
}
public TicketRules(Ticket ticket)
{
theTicket = ticket;
}
public void Execute()
{
ExecuteWith(null, null);
}
public void ExecuteWith(AddTicketParameters param)
{
ExecuteWith(param, null);
}
public virtual void ExecuteWith(AddTicketParameters param, Ticket outsideTicket)
{
foreach (ITicketRule rule in allRules)
{
rule.ExecuteWith(param, theTicket ?? outsideTicket);
}
}
public TicketRules RequireValidation()
{
CreateModifierRule(ticket => ticket.NeedValidation = true);
return this;
}
public TicketRules TotalMilageIs(int milage)
{
CreateModifierRule(ticket => ticket.TotalMilage = milage);
return this;
}
private void CreateModifierRule(Action<Ticket> function)
{
AddRule(new ModifierTicketRule(function));
}
internal void AddRule(ITicketRule rule)
{
allRules.Add(rule);
}
public WhenClauseTicketRule When(Predicate<AddTicketParameters> predicate)
{
WhenClauseTicketRule whenClause = new WhenClauseTicketRule();
whenClause.Predicate = predicate;
AddRule(whenClause);
return whenClause;
}
public TicketRules UseStandardFormulaForTotalMilageAndTime()
{
AddRule(new StandardFormulaTicketRule());
return this;
}
public TicketRules EnsureMinimumMilageIs(int milage)
{
AddRule(new EnsureMinimumMilageTicketRule(milage));
return this;
}
}
the ITicketRules
internal interface ITicketRule : IHideObjectMembers
{
void ExecuteWith(AddTicketParameters param, Ticket ticket);
}
I also need to support the subclasses of AddTicketParameters in the When clause (I've though maybe using generics for that part). I'm posting here because I'm all confused in my design and the Martin Fowler articles confuse me even more.
This is known as the finishing problem when method chaining
Try this
TicketRules
.RequireValidation()
.When(quartType => quartType == QuartType.Before,
rule => rule.TotalMilageIs(64))
.When(quartType => quartType == QuartType.After,
rule => rule.TotalMilageIs(128));
It looks a little odd at first, but it wraps your conditionals into a different scope so you can conditionally execute them. Think about it like creating your own if block. By closing it, you know when you can "finish" a sub statement.