Cross AppDomain Tasks

As a part of plugin system, I build a framework that allows you to host plugins in current app domain, new app domain or external process host. The next channel is to run an long running task in new app domain and control it from any side of wire and here is the simple API with help of two classes..

public class RemoteTask : MarshalByRefObject
 {
 private readonly EventWaitHandle _completionEvent;
 
 public bool IsCanceled { get; protected set; }

 public bool IsCompleted { get; protected set; }

 public Exception Exception { get; protected set; }

 public bool IsFaulted { get; protected set; }

 public string Id { get; private set; }

 
 protected RemoteTask(CancellationToken cancellationToken)
 {
 Id = Guid.NewGuid().ToString();
 _completionEvent = new EventWaitHandle(false, EventResetMode.ManualReset, Id);

 cancellationToken.Register(() =>
 {
 IsCompleted = false;
 IsCanceled = true;
 Finished();
 });
 }

 public RemoteTask(CancellationToken cancellationToken, TaskAwaiter awaiter) : this(cancellationToken)
 {
 awaiter.OnCompleted(() =>
 {
 try
 {
 awaiter.GetResult();
 IsFaulted = false;
 IsCompleted = awaiter.IsCompleted;
 }
 catch (Exception exception)
 {
 Exception = exception;
 IsFaulted = true;
 }
 Finished();
 });
 }

 protected void Finished()
 {
 _completionEvent.Set();
 }

 public static void WaitWorker(RemoteTask worker)
 {
 var waiter = new EventWaitHandle(false, EventResetMode.ManualReset, worker.Id);
 waiter.WaitOne();
 }
 }

And class RemoteTaskOfT if you need results out from your task

public class RemoteTask : RemoteTask
    {
        public RemoteTask(CancellationToken cancellationToken, TaskAwaiter awaiter):base(cancellationToken)
        {
            awaiter.OnCompleted(() =>
            {
                try
                {
                    Result = awaiter.GetResult();
                    IsFaulted = false;
                    IsCompleted = awaiter.IsCompleted;
                }
                catch (Exception exception)
                {
                    Exception = exception;
                    IsFaulted = true;
                }
                Finished();
            });
        }

        public T Result { get; private set; }
    }

to use it from inside the new app domain
just return new RemoteTask(cancellationToken, task.GetAwaiter())
and on client side use
RemoteTask.WaitWorker(worker);
int result = worker.Result;
Exception ex = worker.Exception;

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s