Я читал об этом deadlock condition, что я уверен, что это влияет на мой код (см. Ниже). Я не понимаю: этот код отлично работал на Windows Server 2003 (.net 2.0) в течение последних 12 лет. Теперь мы пытаемся перенести его на Windows Server 2012, где он всегда блокируется.Исключение процесса. Подождите, когда вы закончите()/StandardOutput, состояние взаимоблокировки
Хотя мои DLL-файлы построены для «anyCPU» (по-прежнему нацеливаются на .net 2.0), исполняемый процесс, который выполняется, абсолютно 32-битный, а переход с Server 2003 на Server 2012 происходит от 32-битного до 64- разрядной ОС.
Я думаю, что я понимаю, что делать, чтобы решить проблему, но кто-нибудь знает, почему это поведение изменилось бы с Server 2003 на Server 2012?
public string DoMyProcess(string filenameAndPath, string arguments)
{
string stdout="";
int exitCode = 0;
try
{
ProcessStartInfo procStartInfo = new ProcessStartInfo();
procStartInfo.FileName = filenameAndPath;
procStartInfo.CreateNoWindow = true;
procStartInfo.Arguments = arguments;
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
System.Diagnostics.Process theProcess = null;
try
{
theProcess = Process.Start(procStartInfo);
theProcess.WaitForExit();
exitCode = theProcess.ExitCode;
// moving this ABOVE WaitForExit should eliminate deadlocks
// But why did it always work on Server 2003 but not on Server 2012?
stdout = theProcess.StandardOutput.ReadToEnd();
}
catch (System.Exception e)
{
string errMsg = e.Message;
log_the_error("threw an exception: " + e.Message);
}
}
return stdout;
}
UPDATE:
Mystery тупиковый все еще существует, даже после изменения приведенного выше кода в соответствии с рекомендациями:
try
{
theProcess = Process.Start(procStartInfo);
stdout = theProcess.StandardOutput.ReadToEnd();
}
catch (System.Exception e)
{
string errMsg = e.Message;
log_the_error("threw an exception: " + e.Message);
}
}
Какие другие условия могут привести к этой тупиковой ситуации? Если бы я изучил StandardError, он бы показал что-нибудь полезное?
UPDATE # 2:
FWIW мы предоставлены другой Windows Server 2003 (32-разрядная версия), которая работает IIS 6. Это была исходная конфигурация машины этого код работал на протяжении 12 лет (с только случайным тупиковая). Наш же код, который накладывает блокировки на Server 2012 IIS 8, НЕ ОТКЛЮЧАЕТСЯ на этом сервере 2003.
Теперь у нас есть свой собственный минимальный и полный код, который воспроизводит проблему. Однако .exe, который мы лицензировали, который выполняется процессом, содержит условия конфиденциальности, которые мешают нам публиковать сообщения. Я понимаю, что здесь не помогают эксперты.
ОДИН СОВЕТ, с которым мы столкнулись, заключается в том, что при запуске через отладчик Visual Studio 2013, установленном на фактическом сервере, процесс не блокируется/зависает, вызывая процесс из браузера ВНЕШНИЙ сервер. И как ни странно - из браузера ON THE SERVER 2012 мы не можем подключиться к этой тестовой странице - браузер просто говорит «подключиться» и, в конечном итоге, отключается (однако другие сайты, размещенные на одном и том же сервере IIS 8, могут быть удалены из браузера на сервере!)
Так как те же параметры командной строки, запускаемые вручную из командной оболочки команд или командной оболочки, отличной от admin, трудно поверить, что это проблема 64-бит/WOW64 с этим 32-разрядный исполняемый файл или требуемые DLL. Мы продолжаем искать места, где наши разрешения могут вызывать проблемы (процесс должен записываться в временную папку, которую мы установили в c: \ temp, пока).
Я знаю, что ошибочный шаблон кода распространен в Интернете, но попробуйте использовать пример MS для [Process.OutputDataReceived Event] (https://msdn.microsoft.com/en-us/library/system.diagnostics .process.outputdatareceived (v = vs.110) .aspx? cs-save-lang = 1 & cs-lang = csharp # code-snippet-2) в качестве отправной точки. Помните, что это событие и другие события процесса поступают на вторичный поток, поэтому планируйте соответственно. – TnTinMn
re: ваше отредактированное обновление, ничего не осталось в коде, который должен вызвать тупик. Это не значит, что нет ... вы не предоставили [mcve], так что невозможно понять, какой другой код может быть здесь работает. Чтение 'StandardError' может показывать или не показывать ничего полезного; вы можете неправильно интерпретировать какую-то ошибку или приглашение пользователя во внешнем процессе как тупик, когда на самом деле он просто ждет вас или что-то еще, чтобы ответить. Обратите внимание, что если вы _do_ перенаправляете 'StandardError', тогда вы вводите возможность тупика и захотите убедиться, что вы это избегаете. –
У меня есть несколько разных ответов SO, которые, отвечая на вопросы, отличные от тех, которые у вас здесь есть, включают примеры перенаправления как «StandardOutput», так и «StandardError» без блокировки кода. Вы можете найти один или несколько из них полезными: http://stackoverflow.com/a/33508142, http://stackoverflow.com/a/26722542 и http://stackoverflow.com/a/38881345 –