void SerializeDeserializeAsync(NamedPipeServerStream pipe, ProcessThreadParams parameters, Action <ProcessThreadResult> callback)
        {
            var formatter = new BinaryFormatter();

            pipe.BeginWaitForConnection((ar) =>
            {
                pipe.EndWaitForConnection(ar);

                var memory = new MemoryStream();
                formatter.Serialize(memory, parameters);

                var lengthBytes = BitConverter.GetBytes((int)memory.Length);
                pipe.Write(lengthBytes, 0, 4);
                memory.WriteTo(pipe);

                var buf = new byte[1024];
                memory  = new MemoryStream();
                AsyncCallback endread = null;
                endread = reader =>
                {
                    int bytesRead = pipe.EndRead(reader);
                    if (bytesRead == 0)
                    {
                        pipe.Close();
                        memory.Position = 0;
                        if (memory.Length != 0)
                        {
                            var result = (ProcessThreadResult)formatter.Deserialize(memory);
                            callback(result);
                        }
                    }
                    else
                    {
                        memory.Write(buf, 0, bytesRead);
                        pipe.BeginRead(buf, 0, buf.Length, endread, null);
                    }
                };

                pipe.BeginRead(buf, 0, buf.Length, endread, null);
            }, null);
        }
        Task <R> StartVariableParamsAndResult <R>(MethodInfo method, ProcessThreadParams parameters, out NamedPipeServerStream pipe)
        {
            if (!(parameters.Target?.GetType().IsSerializable ?? true))
            {
                throw new ArgumentException("Method target must be serializable", nameof(method));
            }
            if (!typeof(R).IsSerializable)
            {
                throw new ArgumentException("Result must be serializable", typeof(R).FullName);
            }
            foreach (var p in parameters.Parameters)
            {
                if (p != null && !p.GetType().IsSerializable)
                {
                    throw new ArgumentException($"Parameter must be serializable", p.GetType().FullName);
                }
            }

            var exited = new TaskCompletionSource <R>();

            var proc = BuildInfo(method, exited);

            var  formatter  = new BinaryFormatter();
            bool resultSet  = false;
            R    taskResult = default(R);

            proc.Process.Exited += (sender, args) =>
            {
                var exitcode = proc.Process.ExitCode;
                if (exitcode == 0)
                {
                    if (resultSet)
                    {
                        exited.SetResult(taskResult);
                    }
                    else
                    {
                        exited.TrySetException(new Exception("ProcessThread failed to pass any result back"));
                    }
                }
                if (exitcode == 1)
                {
                    exited.TrySetCanceled();
                }
                else
                {
                    exited.TrySetException(proc.GetError());
                }
            };

            proc.Start(PriorityClass);

            processes.TryAdd(exited.Task, proc);

            NamedPipeServerStream auxPipe = null;

            if (parameters.Pipe != null)
            {
                auxPipe = new NamedPipeServerStream(parameters.Pipe, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
            }
            pipe = auxPipe;

            SerializeDeserializeAsync(proc.Pipe, parameters, (result) =>
            {
                if (result.IsSuccesseded)
                {
                    taskResult = (typeof(R) != typeof(Void)) ? (R)result.Result : default(R);
                    resultSet  = true;
                }
                else
                {
                    if (result.Result is OperationCanceledException)
                    {
                        exited.TrySetCanceled();
                    }
                    else
                    {
                        exited.SetException((Exception)result.Result);
                    }
                }
            });

            return(exited.Task);
        }