C # Выполнить одно последнее действие при сбое приложения - PullRequest
0 голосов
/ 23 июня 2009

Я не уверен, что есть подходящий термин для того, что я хочу, потому что все, что я пробовал в Google, ничего не скупили.

По сути, при сбое приложения я хотел бы выполнить последнее действие для очистки блокировки записи базы данных.

Я также хотел бы поймать это, когда отладка прекращается с помощью кнопки остановки, поскольку, насколько я понимаю, использование кнопки остановки очень отличается от выхода из приложения обычным процессом в приложении.

Есть ли нормальный способ достичь того, что я пытаюсь сделать? Приложение представляет собой приложение Windows Forms на C #, .NET 3.5, написанное на VS2008.

Приветствия

Ответы [ 7 ]

4 голосов
/ 23 июня 2009

Вы не можете ничего сделать в процессе после его уничтожения.

Ваш единственный способ добиться того, чего вы хотите, это иметь второй процесс, который следил за первым, умирающим, а затем выполнял очистку от его имени.

Вам нужно беспокоиться о сбое второго процесса, или о его гибели и так далее. Нелегко заставить его работать во всех мыслимых случаях, но намного лучше, чем ничего.

1 голос
/ 23 июня 2009

Я не думаю, что можно отловить, когда пользователь останавливает процесс через отладчик, однако вы можете переопределить событие OnUnhandledException , чтобы отловить, когда какие-либо исключения вызываются и не перехватываются вашим приложением.

1 голос
/ 23 июня 2009

Проверьте, помогает ли какое-либо из решений на Обработка завершения процесса приложения для Windows .

1 голос
/ 23 июня 2009

Ответ на ваше первое требование должен иметь (в самом основном):

try
{
    // Main application
}
catch // Though you might not want this
{
}
finally
{
    // This code always executed even if application crashes.
}

Однако при работе с приложениями Windows существуют и другие соображения, которые RichardOD указывает в своих комментариях здесь - http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx и здесь http://msdn.microsoft.com/en-us/library/system.windows.forms.application.threadexception.aspx

Ответом на ваше второе требование является то, что вы не можете перехватить остановку приложения в отладчике (или, по крайней мере, я не сталкивался с этим). Это просто убивает процесс.

Например, если вы остановились в точке останова, а затем нажали «Стоп», код не переходит к завершению - он просто завершается.

То же самое верно, если приложение останавливается из-за какого-либо внешнего фактора, например, при отключении питания. В подобных сценариях программа не может выполнить любой код, независимо от того, находится он в блоке finally или нет!

Тем не менее, я только что натолкнулся на этот вопрос Visual Studio: выполнение кода очистки при остановке отладки , ответ на который гласит:

Вы можете использовать DTE (VisualStudio Модель автоматизации) написать макрос это будет вызвано при остановке отладки случается, ниже приведен фрагмент идея.

Private Sub DebuggerEvents_OnEnterDesignMode(ByVal Reason As EnvDTE.dbgEventReason, ByRef ExecutionAction As EnvDTE.dbgExecutionAction) Handles DebuggerEvents.OnEnterDesignMode

    If (Reason = dbgEventReason.dbgEventReasonStopDebugging) Then
        // DO YOUR CLEAN UP CODE HERE
    End If
End Sub

Так что, хотя вы не можете перехватить остановку выполнения в своем приложении, вы можете что-то с этим сделать в Visual Studio.

ПРИМЕЧАНИЕ: Ответ предоставлен Shay Erlichmen not me!

0 голосов
/ 23 июня 2009

«Нормальный способ добиться того, что вы пытаетесь», - убедиться, что ваше приложение никогда не падает.

Вы также можете предоставить отдельное приложение, которое позволит системному администратору снимать любые блокировки файлов, которые могут быть оставлены по какой-либо причине (отключение питания, ...). Такое приложение также может быть использовано для исправления этого.

0 голосов
/ 23 июня 2009

Если вы ориентируетесь на Windows Vista (или выше), вас может заинтересовать API RegisterApplicationRecoveryCallback ...

http://msdn.microsoft.com/en-us/library/aa373345.aspx

Это не относится к сценарию отладки, но позволяет вам что-то делать, когда ваше приложение вот-вот рухнет.

Вы можете p / вызвать этот API из C # (я сделал это), но имейте в виду, что когда вызывается ваш обратный вызов, ваше приложение уже находится в очень плохом состоянии, и вы можете сделать очень мало предположений о состоянии вашей памяти. Если у вас есть какие-либо данные в памяти, которые вы хотите использовать в этой подпрограмме, я бы поставил их в статическом виде в очень общем объеме, чтобы у вас была максимальная вероятность того, что они не будут «прибраны» при выполнении процедуры обратного вызова. работает.

Есть несколько других интересных API, связанных с этим, которые позволяют автоматически перезапускать ваше приложение после сбоя и т. Д.

0 голосов
/ 23 июня 2009

Вы можете подписаться на событие Application.ThreadException при запуске вашей программы, прежде чем вызывать Application.Run. Это даст вам возможность что-то сделать, если ваше приложение сгенерирует исключение. Однако он ничего не сделает для отладки, когда вы нажмете стоп.

<SecurityPermission(SecurityAction.Demand, Flags:=SecurityPermissionFlag.ControlAppDomain)> _
Public Shared Sub Main()
  AddHandler Application.ThreadException, AddressOf ErrorHandlerForm.Form1_UIThreadException
  Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException)

   ' Run the application.
  Application.Run(New Form1())
End Sub


Private Shared Sub Form1_UIThreadException(ByVal sender As Object, ByVal t As ThreadExceptionEventArgs)
  ' Handle exception
End Sub

Другой вариант заключается в том, чтобы просто окружить ваш Application.Run в блоке Try ... Catch, который должен дать вам аналогичные результаты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...