Please consider the following simple code and then I will ask my question.
public static void Save(XmlDocument saveBundle)
{
ThreadStart threadStart = delegate
{
SaveToDatabase(saveBundle);
};
new Thread(threadStart).Start();
}
The issue with using threads in Visual Studio (2005) is you can't walk through them easily (I believe there is a way to switch threads which I have not looked into as I'm hoping there is an easier way).
So, in live, my code is more complex that then example above and we use a new thread as it's time critical but the principal is the same. Most importantly, it is not time critical in test!
At the moment, I will probably do something like using the #if debug but it just feels wrong to do so - Am I using the #if in the correct way here or is there a better way to resolve this?
public static void Save(XmlDocument saveBundle)
{
#if debug
{
SaveToDatabase(parameters);
}
#else
{
ThreadStart threadStart = delegate
{
SaveToDatabase(parameters);
};
new Thread(threadStart).Start();
}
#endif
}
}
Although I'm stuck on .NET 2.0 I am interested in any version from .NET 20. onwards (I'm sure one day I'll leave the Jurassic period and join everyone else)
I would say that your original code is lacking an important feature; some sort of mechanism of reporting back when the operation has completed (or failed):
public static void Save(XmlDocument saveBundle, Action<Exception> completedCallback)
{
ThreadStart threadStart = delegate
{
try
{
SaveToDatabase(saveBundle);
completedCallback(null);
}
catch (Exception ex)
{
completedCallback(ex);
}
};
new Thread(threadStart).Start();
}
That way, you can use some sort of synchronization method to orchestrate your unit-test:
Exception actualException = null;
using (AutoResetEvent waitHandle = new AutoResetEvent(false))
{
instance.Save(xmlDocument, ex =>
{
actualException = ex;
waitHandle.Set();
});
waitHandle.WaitOne();
}
Assert.IsNull(actualException);
If what you truly want to do is not use the threading in your debug build - this is the correct way to do it and probably the quickest and most capable way of doing it as well. It may look a bit ugly but the alternative are just more bools, configurations and other work arounds.
If you're interested in debugging the thread directly (this is important perhaps if concurrency is an issue! You should always test as close to the production environment as possible) then you can simply go (Debug -> Windows -> Threads) and then right click the thread you would like to debug and "Switch to Thread".
Maybe You could put this threading code into a separate method and substitute that method when testing.
virtual void SaveToDBInSeparateThread(...)
{
ThreadStart threadStart = delegate
{
...
};
new Thread(threadStart).Start();
}
You could then instead of returning void return the thread run or something similar.
Or You can add an input parameter to Your method like below:
virtual void SaveToDB(bool inSeparateThread)
{
if(inSeparateThread)
{
ThreadStart threadStart = delegate
{
...
};
new Thread(threadStart).Start();
}
...
}
Or You can provide some kind of DatabaseSavingContext:
interface IDBSaveContext
{
public void SaveToDB(...)
}
And use different implementation (threaded, non-threaded) of this interface depending on execution type.
Related
I'm attempting to write a thread-safe method which may only be called once (per object instance). An exception should be thrown if it has been called before.
I have come up with two solutions. Are they both correct? If not, what's wrong with them?
With lock:
public void Foo()
{
lock (fooLock)
{
if (fooCalled) throw new InvalidOperationException();
fooCalled = true;
}
…
}
private object fooLock = new object();
private bool fooCalled;
With Interlocked.CompareExchange:
public void Foo()
{
if (Interlocked.CompareExchange(ref fooCalled, 1, 0) == 1)
throw new InvalidOperationException();
…
}
private int fooCalled;
If I'm not mistaken, this solution has the advantage of being lock-free (which seems irrelevant in my case), and that it requires fewer private fields.
I am also open to justified opinions which solution should be preferred, and to further suggestions if there's a better way.
Your Interlocked.CompareExchange solution looks the best, and (as you said) is lock-free. It's also significantly less complicated than other solutions. Locks are quite heavyweight, whereas CompareExchange can be compiled down to a single CAS cpu instruction. I say go with that one.
The double checked lock patter is what you are after:
This is what you are after:
class Foo
{
private object someLock = new object();
private object someFlag = false;
void SomeMethod()
{
// to prevent locking on subsequent calls
if(someFlag)
throw new Exception();
// to make sure only one thread can change the contents of someFlag
lock(someLock)
{
if(someFlag)
throw new Exception();
someFlag = true;
}
//execute your code
}
}
In general when exposed to issues like these try and follow well know patters like the one above.
This makes it recognizable and less error prone since you are less likely to miss something when following a pattern, especially when it comes to threading.
In your case the first if does not make a lot of sense but often you will want to execute the actual logic and then set the flag. A second thread would be blocked while you are executing your (maybe quite costly) code.
About the second sample:
Yes it is correct, but don't make it more complicated than it is. You should have very good reasons to not use the simple locking and in this situation it makes the code more complicated (because Interlocked.CompareExchange() is less known) without achieving anything (as you pointed out being lock less against locking to set a boolean flag is not really a benefit in this case).
Task task = new Task((Action)(() => { Console.WriteLine("Called!"); }));
public void Foo()
{
task.Start();
}
public void Bar()
{
Foo();
Foo();//this line will throws different exceptions depends on
//whether task in progress or task has already been completed
}
This is the method in question:
public void StartBatchProcessing(IFileBatch fileBatch)
{
var dataWarehouseFactsMerger = m_dataWarehouseFactsMergerFactory.Create(fileBatch);
dataWarehouseFactsMerger.Merge();
if(!m_isTaskStarted)
{
m_isTaskStarted = true;
m_lastQueuedBatchProcessingTask = new TaskFactory().StartNew(() => ProcessBatch(dataWarehouseFactsMerger));
}
else
{
m_lastQueuedBatchProcessingTask = m_lastQueuedBatchProcessingTask.ContinueWith(previous => ProcessBatch(dataWarehouseFactsMerger));
}
}
As you can see I'm using TPL to queue tasks one after the other and I would like to test that the tasks will execute in the order they arrive as soon as the previous one finishes.
The ProcessBatch method is protected so I think it could be overwritten in a derived class and be used to set some flag or something and assert that.
All ideas are welcome and appreciated.
You could create an implementation of DataWarehouseFactsMergerFactory that creates implementations of DataWarehouseFactsMerger that are capable of logging which fileBatch was entered and the start time of each task, but for the rest don't really do anything.
I have code that does very repetitive things such as logging the method entry and exit. In between, I execute some business logic. Is there a way I could handle that with a Delegate?
Here is what I have so far. However, it is really restrictive due to the func parameters I must passing. Anybody has a better idea?
Func<Func<int>, int> logAction = new Func<Func<int>, int>(func =>
{
try
{
Console.WriteLine("Logging...");
return func();
}
finally
{
Console.WriteLine("End Logging...");
}
});
Postsharp is perfect for this- it is an Aspect Orientated Programming library that features compile time weaving, so it wont impact on performance like run time weaving. This probably doesn't explain much if your new to AOP but basically, it will allow you to declare logging on a method like this:
<Logging> //apply an aspect that will log entrance/exit of method
void MyMethod(params)
{
//do something that might throw an exception (or not)
}
For an example (and source code) on using postsharp for logging, see http://www.sharpcrafters.com/solutions/logging
It seems that one of the AOP frameworks could solve your issue.
private void LogAction(string title, Action action)
{
Logger.Write(string.Format("Entering %0", title));
action();
Logger.Write(string.Format("Leaving %0", title));
}
Sample usage with no return value:
LogAction("DoSomething", () => DoSomething());
Sample usage with return value:
int intResult = 0;
LogAction("Square", () => intResult = Square(4, 4));
The easiest way to do this is to wrap everything inside of an Action and then just execute that in a method
public void log(Action methodToExecute)
{
try
{
Console.WriteLine("Logging...");
methodToExecute();
}
finally
{
Console.WriteLine("End Logging...");
}
}
Then call it creating a generic action for your function
//no return
log(() => yourFunciton(optionalParmeters));
//return to something
log(() => someVar = yourFunction(optionalParameters));
I was writing some try-catch blocks for various methods today, and thought to myself it would be good to have utility method which would automatically call the method again for a number of times specified in a parameter, at a certain time.
However, I thought to myself, the method/property etc which will cause an exception will be at the top of the stacktrace (do property calls get put on the stacktrace?) in a single threaded application (so an application with no code relating to threading). So I can simply get the method name at the top and dynamically call it again.
So I would have code like:
string s = StackTrace.GetFrame(0).GetMethodName; (I can't remember the exact syntax).
With this method, I can execute it using an activator or one of several other ways.
But in a multi-threaded application, I could have several methods firing at once and I wouldn't know which one finishes first/last. So I can't expect a method for which I write a try-catch block to be at the top of the stack.
How would I go about achieving this?
Please don't do this. It's a really, really, really, really, really bad idea.
Maybe not as bad as deleting files randomly, if the hard drive runs out of room - but just about as bad.
While I question the need for an auto retrying mechanism (does randomly retrying really help you out in so many situations that you need a utility method?) - using StackTrace and Reflection is, at best, a terribly complicated solution.
Not that I suggest that anyone actually use this code, but I'd probably go with a delegate based approach to this particular problem:
public static class Extensions {
public static void Try(this Action a, int maxTries) {
new (Func<bool>(() => { a(); return true; })).Try(maxTries);
}
public static TResult Try<TResult>(this Func<TResult> f, int maxTries) {
Exception lastException = null;
for (int i = 0; i < maxTries; i++) {
try {
return f();
} catch (Exception ex) {
lastException = ex;
}
}
throw lastException;
}
}
Usage is a bit unorthodox, but fairly clear I think:
// Set a property
new Action(() => myObject.Property = 5).Try(5);
// With a return value
var count = new Func<int>(() => myList.Count).Try(3);
You can't inline a lambda to a method, but you could have a somewhat fluent interface:
Utilities.Try(
() => MyObject.Property = 5
).Repeat(5);
And multi line methods:
Utilities.Try(() => {
MyObject.Property1 = 5;
MyObject.Property2 = 6;
MyObject.Property3 = 7;
}).Repeat(5);
Mark's code is probably better, but here's mine...
If you really want to do something like this, I'd use code something like this. Yes, you still have to manually call it, but your idea of indiscriminately retrying ALL excepting methods is a really, really bad idea.
public class TryAgain
{
public delegate void CodeToTryAgain ();
public static void Repeat<E>(int count, CodeToTryAgain code) where E : Exception
{
while (count-- > 0)
{
try
{
code();
return;
}
catch (E ex)
{
Console.WriteLine("Caught an {0} : {1}", typeof(E).Name, ex.Message);
// ignoring it!
}
}
}
}
And then you'd call your failing method, ThrowTwice, or whatever you want to do, like this:
TryAgain.Repeat<MyException>(5, delegate()
{
ThrowTwice();
});
In this example, the Repeat method will ignore all exceptions of type MyException, trying to call ThrowTwice up to 5 times...
You can add your own sleeping and time-outs, and whatever.
I've never been completely happy with the way exception handling works, there's a lot exceptions and try/catch brings to the table (stack unwinding, etc.), but it seems to break a lot of the OO model in the process.
Anyway, here's the problem:
Let's say you have some class which wraps or includes networked file IO operations (e.g. reading and writing to some file at some particular UNC path somewhere). For various reasons you don't want those IO operations to fail, so if you detect that they fail you retry them and you keep retrying them until they succeed or you reach a timeout. I already have a convenient RetryTimer class which I can instantiate and use to sleep the current thread between retries and determine when the timeout period has elapsed, etc.
The problem is that you have a bunch of IO operations in several methods of this class, and you need to wrap each of them in try-catch / retry logic.
Here's an example code snippet:
RetryTimer fileIORetryTimer = new RetryTimer(TimeSpan.FromHours(10));
bool success = false;
while (!success)
{
try
{
// do some file IO which may succeed or fail
success = true;
}
catch (IOException e)
{
if (fileIORetryTimer.HasExceededRetryTimeout)
{
throw e;
}
fileIORetryTimer.SleepUntilNextRetry();
}
}
So, how do you avoid duplicating most of this code for every file IO operation throughout the class? My solution was to use anonymous delegate blocks and a single method in the class which executed the delegate block passed to it. This allowed me to do things like this in other methods:
this.RetryFileIO( delegate()
{
// some code block
} );
I like this somewhat, but it leaves a lot to be desired. I'd like to hear how other people would solve this sort of problem.
This looks like an excellent opportunity to have a look at Aspect Oriented Programming. Here is a good article on AOP in .NET. The general idea is that you'd extract the cross-functional concern (i.e. Retry for x hours) into a separate class and then you'd annotate any methods that need to modify their behaviour in that way. Here's how it might look (with a nice extension method on Int32)
[RetryFor( 10.Hours() )]
public void DeleteArchive()
{
//.. code to just delete the archive
}
Just wondering, what do you feel your method leaves to be desired? You could replace the anonymous delegate with a.. named? delegate, something like
public delegate void IoOperation(params string[] parameters);
public void FileDeleteOperation(params string[] fileName)
{
File.Delete(fileName[0]);
}
public void FileCopyOperation(params string[] fileNames)
{
File.Copy(fileNames[0], fileNames[1]);
}
public void RetryFileIO(IoOperation operation, params string[] parameters)
{
RetryTimer fileIORetryTimer = new RetryTimer(TimeSpan.FromHours(10));
bool success = false;
while (!success)
{
try
{
operation(parameters);
success = true;
}
catch (IOException e)
{
if (fileIORetryTimer.HasExceededRetryTimeout)
{
throw;
}
fileIORetryTimer.SleepUntilNextRetry();
}
}
}
public void Foo()
{
this.RetryFileIO(FileDeleteOperation, "L:\file.to.delete" );
this.RetryFileIO(FileCopyOperation, "L:\file.to.copy.source", "L:\file.to.copy.destination" );
}
You could also use a more OO approach:
Create a base class that does the error handling and calls an abstract method to perform the concrete work. (Template Method pattern)
Create concrete classes for each operation.
This has the advantage of naming each type of operation you perform and gives you a Command pattern - operations have been represented as objects.
Here's what I did recently. It has probably been done elsewhere better, but it seems pretty clean and reusable.
I have a utility method that looks like this:
public delegate void WorkMethod();
static public void DoAndRetry(WorkMethod wm, int maxRetries)
{
int curRetries = 0;
do
{
try
{
wm.Invoke();
return;
}
catch (Exception e)
{
curRetries++;
if (curRetries > maxRetries)
{
throw new Exception("Maximum retries reached", e);
}
}
} while (true);
}
Then in my application, I use c#'s Lamda expression syntax to keep things tidy:
Utility.DoAndRetry( () => ie.GoTo(url), 5);
This calls my method and retries up to 5 times. At the fifth attempt, the original exception is rethrown inside of a retry exception.