D>Полагаю, что вы можете убедиться в этом с помощью несложного практического эксперимента.
Application: WindowsService1.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.Web.Query.Dynamic.ParseException
at WindowsService1.Service1.Run()
at System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
at System.Threading.ThreadHelper.ThreadStart()
код
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using System.Threading;
namespace WindowsService1 {
public partial class Service1 : ServiceBase {
public Service1() {
InitializeComponent();
}
protected override void OnStart(string[] args) {
new Thread(Run).Start();
}
protected override void OnStop() {
}
void Run() {
throw new System.Web.Query.Dynamic.ParseException("", 0);
}
}
}
Здравствуйте, m2user, Вы писали:
M>Но что касается Windows Service, то от обычного консольного приложения он по сути отличается только обработкой RPC запросов от Service Control Manager и регистрацией в реестре. M>И от неперехваченных исключений падает точно также, как любое консольное приложение.
Да, действительно это так. Занятно, что в FW 1.0/1.1 исключение выброшенное не из главного потока не приводило к завершению процесса.
In the .NET Framework versions 1.0 and 1.1, an unhandled exception that occurs in a thread other than the main application thread is caught by the runtime and therefore does not cause the application to terminate. Thus, it is possible for the UnhandledException event to be raised without the application terminating. Starting with the .NET Framework version 2.0, this backstop for unhandled exceptions in child threads was removed, because the cumulative effect of such silent failures included performance degradation, corrupted data, and lockups, all of which were difficult to debug.
QC>Похоже причина в этом QC> GC.Collect(2, GCCollectionMode.Forced); QC> GC.WaitForPendingFinalizers();
Ну да, WaitForPendingFinalizers может висеть неопределенное время в зависимости от того, что застряло в очереди на финализацию.
Если ты повторил проблему и снял дамп, то через WinDbg можно посмотреть, что висит в finalizer queue.
Вообще в норме не следует вызывать GC.Collect и GC.WaitForPendingFinalizers вручную. Присутствие их в коде уже повод насторожиться.
Здравствуйте, m2user, Вы писали:
QC>>Похоже причина в этом QC>> GC.Collect(2, GCCollectionMode.Forced); QC>> GC.WaitForPendingFinalizers();
M>Ну да, WaitForPendingFinalizers может висеть неопределенное время в зависимости от того, что застряло в очереди на финализацию. M>Если ты повторил проблему и снял дамп, то через WinDbg можно посмотреть, что висит в finalizer queue.
M>Вообще в норме не следует вызывать GC.Collect и GC.WaitForPendingFinalizers вручную. Присутствие их в коде уже повод насторожиться.
Нет, не снял, просто больше не вижу что могло зависнуть.
QC>Нет, не снял, просто больше не вижу что могло зависнуть.
Если предполагаешь, что именно в этом дело, то можно просто и без воспроизведения снять дамп и посмотреть, сколько объектов в finalizer queue. В идеале их должно быть относительно мало (объекты у которых ты не имеешь возможности явно вызвать Dispose — например Thread и т.п.).
Ну и добавить трассировку времени выполнения GC.Collect и GC.WaitForPendingFinalizers.