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); }