I have been bitten by a poorly architected solution. It is not thread safe!
I have several shared classes and members in the solution, and during development all
Creating and tearing down an appdomain for each call - I take it you're not worried about performance on this one?
Ideally you should change the called code to be threadsafe.
Which bit, exactly, is being a pain in terms of thread safety? I can't see any static state nor singletons - and there seems to be appropriate "new" objects... am I being blind?
So what is the symptom you are seeing...
An AppDomain answer will be (relatively) slow. As part of a middleware-backed system this might be OK (i.e. the "relatively" is in the same ball-park).
If you do have some static state somewhere, another option that sometimes works is [ThreadStatic] - which the runtime interprets as "this static field is unique per thread". You need to be careful with initialization, though - the static constructor on thread A might assign a field, but then thread B would see a null/0/etc.
Why not just put a lock around the code you want to execute sequentially? It will be a bottleneck, but it should work in a multithreaded environment.
public class Loader
{
private static object SyncRoot = new object();
private string connectionString;
private string fileName;
private Stream stream;
private DataFile dataFile;
public Loader(Stream stream, string fileName, string connectionString)
{
this.connectionString = connectionString;
this.fileName = fileName;
this.stream = stream;
}
public void Process()
{
lock(SyncRoot) {
dataFile = new DataFile(aredStream, fileName, connectionString);
dataFile.ParseFile();
dataFile.Save();
}
}
}
Just for completeness.
I did find that if I marked the send adapter as "Ordered Delivery" in the "Transport Advanced Options" dialog I was able to avoid the multi-thread issues I was having.
I figure this is another possible answer to my problem, but not necessarily to the question.
If you have shared statics that are conflicting with each other, then you might want to try adding [ThreadStatic] attribute to them. This will make them local to each thread. That may solve your problem in the short term. A correct solution would be to simply rearchitect your stuff to be thread-safe.
Using app domains you could do something like this:
public class Loader
{
private string connectionString;
private string fileName;
private Stream stream;
private DataFile dataFile;
public Loader(Stream stream, string fileName, string connectionString)
{
this.connectionString = connectionString;
this.fileName = fileName;
this.stream = stream;
}
public void Process()
{
//***** Create AppDomain HERE *****
string threadID = Thread.CurrentThread.ManagedThreadId.ToString();
AppDomain appDomain = AppDomain.CreateDomain(threadID);
DataFile dataFile =
(DataFile) appDomain.CreateInstanceAndUnwrap(
"<DataFile AssemblyName>",
"DataFile",
true,
BindingFlags.Default,
null,
new object[]
{
aredstream,
filename,
connectionString
},
null,
null,
null);
dataFile.ParseFile();
dataFile.Save();
appDomain.Unload(threadID);
}
}