2009-06-04 15 views
4

Я показываю заставку на фоновом потоке, пока загружается моя программа. Когда он загружается, я прерываю Thread, так как это единственная цель - показать всплывающее окно Now Loading.Как подавить ошибку thread.abort() C#?

Моя проблема заключается в том, что при прерывании потока он выбрасывает ThreadAbortException, чтобы пользователь мог просто нажать «Продолжить».

Как я могу справиться с этим? Я пытался подавить его, как так ->

  try 
     { 
      Program.splashThread.Abort(); 
     } 
     catch(Exception ex) 
     { 

     } 

, но у меня есть ощущение, что собирается получить меня наорал на здесь, и это не работает так, как.

Спасибо!

+4

Я на самом деле недавно написал о создании заставки. Посмотрите, поможет ли это вам: http://crazorsharp.blogspot.com/2009/06/creating-splash-screen-in-net-with.html BFree

+2

Если вам нужно использовать Thread.Abort, повторять что-то неправильно (вообще). Попытайтесь найти другой, более безопасный способ. Много хороших предложений ниже. –

+1

@BFree: Если бы я мог бы дать вам долю в ответе! Благодарим вас за конструктивную обратную связь. Я так много учусь с вашего поста! В то время как другой ответ получил мое текущее решение для работы, я ожидаю, что создам более надежный Splash из информации в вашем блоге. Спасибо! –

ответ

20

Вам не нужно отменять нить. Я приведу пример с кодом.

В виде заставки:

public void CloseSplash() 
{ 
    Invoke((MethodInvoker)delegate 
    { 
     this.Close(); 
    }); 
} 

В программе.CS-файл:

private static Splash _splash = null; 
public static void CloseSplash() 
{ 
    if (_splash!= null) 
    { 
     _splash.CloseSplash(); 
    } 
} 

Теперь, когда начинается ваш главный метод, показать всплеск в теме:

Thread t = new Thread(new ThreadStart(delegate 
{ 
    _splash = new Splash(); 
    _splash.ShowDialog(); 
})); 

t.Start(); 

... и когда вы хотите, чтобы закрыть, просто закрыть его:

Program.CloseSplash(); 

Тогда вам не нужно беспокоиться о прерывании потока; он выйдет изящно.

+2

Спасибо, что показал мне лучший способ сделать это. Конструктивная обратная связь очень ценится! –

3

Изменения типа исключения ThreadAbortException и добавить вызов ResetAbort()

try 
    { 
     Program.splashThread.Abort(); 
    } 
    catch(ThreadAbortException ex) 
    { 
     Thread.ResetAbort(); 
    } 

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

+0

Если я закрою форму всплеска и что ВСЕ, что делал нить, будет уничтожать мой поток? –

9

Пожалуйста, обратитесь к следующей ссылке, полученный, выполнив поиск Google (первый возвращаемый результат):

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

Обратите особое внимание на эту часть:

Когда этот метод вызывается в потоке, система бросает в поток поток ThreadAbortException, чтобы прервать его. ThreadAbortException - специальное исключение, которое может быть уловлено кодом приложения, но повторно выбрано в конце блока catch, если не вызвано ResetAbort. ResetAbort отменяет запрос на прерывание и предотвращает прекращение потока Thread4b. Незавершенные блоки finally выполняются до того, как поток будет прерван.

+0

Я как раз собирался опубликовать это. Другими словами, то, что он хочет сделать, вероятно, невозможно. –

1

Зачем вам это делать? Просто установите флаг, который опросит поток, а затем, когда поток подберет его, он закроется.

7

Использование Threadabort не рекомендуется. Это зло. Почему бы не использовать другой механизм, например (Auto/Manual) ResetEvent? Запустите поток с помощью заставки, подождите события. Если другой код выполнен с загрузкой, установите событие en, ​​чтобы экран заставки закрыл обычный (хороший) способ.

+0

Взял слова прямо из моего рта ;-) Я даже собирался написать, что Thread.Abort() - это зло, ха-ха. –

4

Некоторые моменты. Исключение ThreadAbort - причина, по которой поток прерывается. Это не побочный эффект, который вы вызываете. Когда вы вызываете прерывание в потоке, среда выполнения заставляет исключение threadabort исключаться в поток. Это исключение можно поймать, потому что оно позволяет пользователю выполнить некоторую очистку до прекращения потока.

Исключение затем автоматически обновляется, чтобы гарантировать, что поток прерван. Если исключение было поймано, и если оно не было восстановлено, поток никогда не прерывается.

Действительно интеллектуальный дизайн на самом деле.

Так что это действительно нормально, чтобы поймать это исключение. На самом деле вы должны. Но поймайте только это конкретное исключение, а не общее исключение. (как показано ниже)

catch(ThreadAbortException ex) 
{ 
    //This is an expected exception. The thread is being aborted 
} 
+0

Спасибо вам большое! –

0

Я использовал решение, предложенное Фредриком Мёрком. Это очень ясно и элегантно. В противном случае я нашел проблему, если мы создаем экземпляр формы всплеска перед запуском реального приложения (application.run (mainform ...)):

он вызывает недопустимое исключениеOprationException, вызванное тем, что форма-дескриптор еще не существует в call- нить. Чтобы создать ручку непосредственно в нити т (и пропустить это исключение!) Пытаются запустить форму выплеска таким образом:

Thread t = new Thread(new ThreadStart(delegate 
{ 
    _splash = new Splash(); 
    Application.Run(_splash); 
})); 

t.Start(); 

и, если вы планируете вызвать метод closeSplash в более ветвей программы , принудительно введите нулевое значение после первого вызова:

private static Splash _splash = null; 
    public static void CloseSplash() 
    { 
     if (_splash!= null) 
     { 
      _splash.CloseSplash(); 
      _splash=null; 
     } 
} 
1

Попробуйте этот код. Это отлично работает для меня.

void splash() 
{ 
    try { 
     SplashScreen.SplashForm frm = new SplashScreen.SplashForm(); 
     frm.AppName = "HR"; 

     Application.Run(frm); 
    } 
    catch (ThreadAbortException ex) 
    { 
     Thread.ResetAbort(); 
    } 
} 
Смежные вопросы