簡體   English   中英

如何抑制thread.abort()錯誤C#?

[英]How do I suppress a thread.abort() error C#?

我的程序加載時,我在后台線程上顯示啟動畫面。 加載后我將中止線程,因為它的唯一目的是顯示一個正在加載的初始形式。

我的問題是,當中止一個Thread時,它會拋出一個ThreadAbortException ,用戶只需單擊Continue on。

我該如何處理? 我試圖壓制它 - >

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

        }

但我有一種感覺,這會讓我在這里大吼大叫,它無論如何都行不通。

謝謝!

您無需取消該帖子。 我將用代碼舉例說明。

在啟動畫面中:

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

在Program.cs文件中:

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

現在,當Main方法啟動時,在線程中顯示啟動:

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

t.Start();

...當你想要它關閉時,只需關閉它:

Program.CloseSplash();

然后你不必擔心中止線程; 它會優雅地退出。

請參閱以下鏈接獲取Google搜索(返回的第一個結果):

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

特別注意這部分:

在線程上調用此方法時,系統會在線程中拋出ThreadAbortException以中止它。 ThreadAbortException是一個特殊的異常,可以被應用程序代碼捕獲,但是在catch塊的末尾重新拋出,除非調用ResetAbort ResetAbort取消中止請求,並阻止ThreadAbortException終止線程。 在線程中止之前執行未執行的finally塊。

不建議使用Threadabort。 這是邪惡的。 為什么不使用像(自動/手動)ResetEvent這樣的其他機制? 使用啟動畫面啟動線程,等待事件。 如果其他代碼已完成加載內容,請設置事件以允許啟動屏幕以正常(好)方式關閉自身。

有些觀點。 ThreadAbort異常是線程中止的原因。 這不是你打電話中止的副作用。 在線程上調用abort時,運行時會強制將threadabort異常傳播到線程。 可以捕獲此異常,因為它允許用戶在線程中止之前執行一些清理。

然后自動重新拋出異常以確保線程被中止。 如果異常被捕獲並且如果沒有重新拋出,則線程永遠不會中止。

實際上真的很聰明。

所以抓住那個例外真的很好。 實際上你應該。 但只抓住那個特定的例外而不是一般的例外。 (如下所示)

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

將異常類型更改為ThreadAbortException並添加對ResetAbort()的調用

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

一般來說,中止線程被認為是非常糟糕的做法,並且可能導致各種難以追蹤的錯誤。 您是否考慮過設置一種方法來關閉啟動窗口或使用某種輪詢來在設置標志時停止線程?

試試這個代碼。 它對我來說很好。

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

        Application.Run(frm);
    }
    catch (ThreadAbortException ex)
    {
        Thread.ResetAbort();
    }
}

為什么要這么做? 只需設置一個線程輪詢的標志,然后最終當線程選中它時它將自行關閉。

我使用了FredrikMörk建議的解決方案。 它非常清晰優雅。 否則,如果我們在啟動真實應用程序(application.run(mainform ...))之前實例化splash表單,我發現了一個問題:

它引發了一個由form-handle引起的invalidOprationException仍然不存在於調用線程中。 要直接在線程t中創建句柄(並跳過此異常!),請嘗試以這種方式啟動splash表單:

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

t.Start();

並且,如果您計划在程序的更多分支中調用closeSplash方法,請在第一次調用后強制使用null值:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM