All articles in Internet says that using Thread.Abort
is evil (because synchronization primitives belongs to operating system, and process doesn't terminate yet, and primitives might remain locked after thread aborting). Developers advises to terminate whole processes instead, because operation system will free synchronization primitives when process stops.
Will AppDomain
unloading help, If one will use Slim
synchronization primitives? (With .net 4.0 several new classes have been added relating to threading: ManualResetEventSlim
, SemaphoreSlim
, ReaderWriterLockSlim
).
Documentation says that these primitives can't be used beween different processes, because implementation code of primitives is fully managed. But I don't understand - will these primitives work through AppDomain
border. (see Can't set synchronization context when using appdomains)
If yes, how they do that? If no, then why documentation omit this limitation?
UPD: All my code is trusted by me, including the code inside the domain which i unload. I don't want to leave the thread working, when the time comes to terminate it. I want to terminate (abort) thread instead of "setting flag" and "making nice architecture". If it is neccessary to create additional thread first (i think this is necessary at start of background processing in separate domain to create one more thread), i will do. I don't want to use "setting flag" approach, because it requires me to instrument background algorithm with flag checks, i shouldn't, it's the runtime or compiler should automate that instrumentation for me. Right now there is no such instrumentation, that is why I am trying to apply the approach with domain unloading.
Adding checks between each instruction (or in deep nested cycles) will slow the code significantly. Adding check in random locations will not give guaranties of prompt termination. If difficulties of writing abort-safe code can be solved, why not to try to abort threads and unload domain?
You misunderstands the AppDomain
, Process
and Thread
definitions - AppDomains always lives in one process, but one process can be a master for different AppDomains
*:
The ability to run multiple applications within a single process dramatically increases server scalability.
Thread
, just for mention.So, the answer for your question is Yes, the slim synchronization primitives will work with various AppDomains
, as there are no cross-process calls in such architecture, only a logical distinction for various processes.
As for the linked question, there are no problem with synchronization primitives there, only with SynchronizationContext
, which is Thread
-specific, but not AppDomain
-specific.
You can find a great answer about the difference between AppDomain
, Thread
and Process
here: Difference between AppDomain, Assembly, Process, and a Thread
As for the unloading the AppDomain, I think that you can refactor your code as you can start a worker Thread
into your AppDomain
with limited access to the system resources, and simply wait for it to be finished, something like it mentioned here:
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main()
{
var ad = AppDomain.CreateDomain("WhereTheWorkHappens");
Task<string> t = DoWorkInOtherDomain(ad);
Console.WriteLine("waiting...");
Console.WriteLine(t.Result);
Console.ReadLine();
}
static Task<string> DoWorkInOtherDomain(AppDomain ad)
{
var ch = new MarshaledResultSetter<string>();
Worker worker = (Worker)ad.CreateInstanceAndUnwrap(typeof(Worker).Assembly.FullName, typeof(Worker).FullName);
worker.DoWork(ch);
return ch.Task;
}
class Worker : MarshalByRefObject
{
public void DoWork(MarshaledResultSetter<string> callback)
{
ThreadPool.QueueUserWorkItem(delegate
{
Thread.SpinWait(500000000);
callback.SetResult(AppDomain.CurrentDomain.FriendlyName);
});
}
}
class MarshaledResultSetter<T> : MarshalByRefObject
{
private TaskCompletionSource<T> m_tcs = new TaskCompletionSource<T>();
public void SetResult(T result) { m_tcs.SetResult(result); }
public Task<T> Task { get { return m_tcs.Task; } }
}
}
As an additional idea for you, you can read about Sandboxing your code with TPL
, which, as I think, is better approach as you don't manually manage the system resources and has less chances for being hacked by your non-trusted code.
Also, you can find a GitHub project with Cross-AppDomain Marshaling friendly TPL wrappers for APM
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With