Ответ 1
Используйте асинхронные операции с BeginRead/BeginWrite и AsyncCallback.
Я хочу установить связь между родительским и дочерним процессами, написанными на С#. Он должен быть асинхронным, управляемым событиями. Я не хочу запускать поток в каждом процессе, который обрабатывает очень редкое сообщение.
Какое лучшее решение для этого?
Используйте асинхронные операции с BeginRead/BeginWrite и AsyncCallback.
Если ваши процессы на одном компьютере, вы можете просто использовать stdio.
Это мое использование скриншота веб-страницы:
var jobProcess = new Process();
jobProcess.StartInfo.FileName = Assembly.GetExecutingAssembly().Location;
jobProcess.StartInfo.Arguments = "job";
jobProcess.StartInfo.CreateNoWindow = false;
jobProcess.StartInfo.UseShellExecute = false;
jobProcess.StartInfo.RedirectStandardInput = true;
jobProcess.StartInfo.RedirectStandardOutput = true;
jobProcess.StartInfo.RedirectStandardError = true;
// Just Console.WriteLine it.
jobProcess.ErrorDataReceived += jp_ErrorDataReceived;
jobProcess.Start();
jobProcess.BeginErrorReadLine();
try
{
jobProcess.StandardInput.WriteLine(url);
var buf = new byte[int.Parse(jobProcess.StandardOutput.ReadLine())];
jobProcess.StandardOutput.BaseStream.Read(buf, 0, buf.Length);
return Deserz<Bitmap>(buf);
}
finally
{
if (jobProcess.HasExited == false)
jobProcess.Kill();
}
Обнаружение аргументов на Главном
static void Main(string[] args)
{
if (args.Length == 1 && args[0]=="job")
{
//because stdout has been used by send back, our logs should put to stderr
Log.SetLogOutput(Console.Error);
try
{
var url = Console.ReadLine();
var bmp = new WebPageShooterCr().Shoot(url);
var buf = Serz(bmp);
Console.WriteLine(buf.Length);
System.Threading.Thread.Sleep(100);
using (var o = Console.OpenStandardOutput())
o.Write(buf, 0, buf.Length);
}
catch (Exception ex)
{
Log.E("Err:" + ex.Message);
}
}
//...
}
Я бы предложил использовать Windows Communication Foundation:
http://en.wikipedia.org/wiki/Windows_Communication_Foundation
Вы можете передавать объекты туда и обратно, использовать различные протоколы. Я бы предложил использовать двоичный протокол tcp.
Именованные каналы в WCF.
Там также COM.
Есть технические возможности, но я бы сказал, что преимущество заключается в том, что вы сможете вызывать методы, которые вы можете определить.
MSDN предлагает обучающие материалы по интерфейсу С# COM. Пожалуйста, ищите, потому что эти ссылки меняются.
Чтобы начать работу прямо сейчас, здесь...
Там также MSMQ (Microsoft Message Queuing), который может работать как в сетях, так и на локальном компьютере. Хотя есть более эффективные способы связи, на которые стоит обратить внимание: https://msdn.microsoft.com/en-us/library/ms711472(v=vs.85).aspx
Наиболее простым решением в С# для межпроцессного взаимодействия, когда безопасность не является проблемой и с учетом ваших ограничений (два процесса С# на одной машине), является Remoting API. Теперь Remoting является устаревшей технологией (не такой, как устаревшая) и не рекомендуется для использования в новых проектах, но она работает хорошо и не требует большого количества пышности и обстоятельств для работы.
На MSDN есть отличная статья об использовании класса IpcChannel
из инфраструктуры Remoting (благодарность Грегу Бичу за поиск здесь) для настройки простого удаленного сервера и клиента.
Я бы предложил сначала попробовать этот подход, а затем попытаться перенести ваш код в WCF (Windows Communication Framework). Который имеет несколько преимуществ (лучшая безопасность, кроссплатформенность), но обязательно более сложный. К счастью, у MSDN есть очень хорошая статья для переноса кода с Remoting на WCF.
Если вы хотите сразу же погрузиться в WCF, здесь есть отличное руководство.