У меня есть служба Windows, настроенная для управления пользовательскими задачами .Net. Организация это:
-Windows Service отслеживает расписание и при необходимости запускает рабочий EXE-файл.
-Worker .exe (легкое приложение winform) использует аргумент командной строки для загрузки библиотеки DLL (плагина) и запуска некоторого кода.
Это хорошо работает уже несколько месяцев. Я недавно перенес его на Server 2012 (из IIRC 2008 года) - это может быть не связано, но трудно сказать. Спустя некоторое время после миграции я столкнулся с проблемой, когда рабочий .exe "запускается" после вызова process.start (), но не достигает моего кода. Никаких ошибок или чего-то еще, просто кажется, что он завис во время загрузки приложения.
Сервисный код, который запускает его, довольно стандартный.
// Create a temp folder and copy the executable to it
// (so the source exe isn't always in use and can be swapped out)
Process p = new Process();
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = Path.Combine(temp.Path, Path.GetFileName(ExecutablePath));
psi.Arguments = CommandLineArgs.ConcatenateList(" ");
psi.UseShellExecute = false;
psi.RedirectStandardError = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.CreateNoWindow = true;
psi.ErrorDialog = false;
psi.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo = psi;
p.Start();
// read standard output if necessary, kill and reschedule if appears to be frozen, etc.
В этот момент запускается исполняемый файл worker - в диспетчере задач он обычно выглядит нормально. Единственное, что подсказывает мне, что что-то пошло не так, - это потребление памяти - в нормальных условиях рабочий достигает около 5 МБ во время запуска и увеличивается, чтобы отразить задачу, но когда процесс зависает, он достигает только около 2 МБ и останавливается.
В качестве доказательства того, что это не мой код в worker, я добавил вызов функции ведения журнала в качестве самой первой строки и никогда не видел журнала.
Сообщений об ошибках нет, и, что действительно странно, это не постоянная проблема. Тот же самый вызов, который сейчас зависает, будет нормально работать через 30 секунд. Также, похоже, нет какой-либо истинной закономерности в том, когда возникает проблема - самое близкое, что я вижу, это то, что иногда это происходит с несколькими задачами одновременно (например, это может повлиять на все задачи, запущенные в то время, когда проблема возникает с любой задачей).
У меня это есть в момент, когда служба может автоматически обнаруживать и обрабатывать ее соответствующим образом, поэтому это не срочная проблема, но все же что-то, что я хотел бы исправить, если причина или решение кому-либо выделяется.
Код инициализации worker - это просто стандартный запуск форм выигрыша, и мои вещи начинают вызываться в form_load.
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// Do Stuff - never gets hit when the freeze happens.
}
Изменить: в комментариях настройте службу для регистрации минидампа с записью журнала, которую он создает, когда видит зависший процесс. Завтра проверю и посмотрю, что из этого выйдет.
Изменить 4 сентября 2015 г.: информация о минидампе:
Минидамп показывает, что код остановлен / застрял при выходе} из static void main, то есть:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
} // <------ This is where the main thread is frozen.
В остальном вроде все нормально.
Я собираюсь провести небольшое исследование и на всякий случай попробовать некоторые изменения в worker.
Редактировать от 4 сентября 2015 г. № 2: скорректирован запуск работника, и он, похоже, работает. Суть этого в том, чтобы удалить ссылку на форму и просто использовать контекст приложения (например, пример кода проекта)
Я забил систему запросами задач, и у нее не было никаких проблем. Я позволю ему поработать на выходных в качестве теста и обновлю статус во вторник. Все еще любопытно, почему он так случайно ломается при загрузке формы.
Код в его нынешнем виде:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new AppContext());
}
}
class AppContext : ApplicationContext
{
public AppContext()
{
// Do Stuff
}
}