1. 程式人生 > >C# try-catch用法

C# try-catch用法

例子查詢出錯時,彈出對話方塊

        private void cxBtn_Click(object sender, EventArgs e)//查詢源啟資料
        {
            try
            {
                s = dtpStatime.Value.Date.ToString().Replace('-', '/');
                ReadOracleData rod = new ReadOracleData();
                DataSet ds = new DataSet();
                ds = rod.CreateCmdsAndUpdate(ReadOracleData.connString2, ReadOracleData.connString1, rod.SQL1, "select * from dzsj;", "dzsj", s);
                dgvJg.DataSource = ds.Tables["dzsj"];
                MessageBox.Show("查詢成功!");
            }
            catch (Exception ex)
            { MessageBox.Show(ex.ToString()); }
        }

具體用法參考:

https://msdn.microsoft.com/zh-cn/library/0yd65esw.aspx

 

Try-catch 語句包含一個後接一個或多個 catch 子句的 try 塊,這些子句指定不同異常的處理程式。

引發異常時,公共語言執行時 (CLR) 查詢處理此異常的 catch 語句。如果當前正在執行的方法不包含此類 catch 塊,則 CLR 檢視呼叫了當前方法的方法,並以此類推遍歷呼叫堆疊。如果未找到任何 catch 塊,則 CLR 向用戶顯示一條未處理的異常訊息,並停止執行程式。

try 塊包含可能導致異常的受保護的程式碼。將執行此塊,直至引發異常或其成功完成。例如,強制轉換 null 物件的以下嘗試會引發 NullReferenceException 異常:

C#
object o2 = null;
try
{
    int i2 = (int)o2;   // Error
}

 

儘管可以不帶引數使用 catch 子句來捕獲任何型別的異常,但不推薦這種用法。一般情況下,只應捕獲你知道如何從其恢復的異常。因此,應始終指定派生自 System.Exception 的物件引數,例如:

C#
catch (InvalidCastException e) 
{
}

 

可以使用同一 try-catch 語句中的多個特定 catch 子句。在這種情況下,catch 子句的順序很重要,因為 catch 子句是按順序檢查的。在使用更籠統的子句之前獲取特定性更強的異常。如果捕獲塊的排序使得永不會達到之後的塊,則編譯器將產生錯誤。
篩選想要處理的異常的一種方式是使用 catch 引數。也可以使用謂詞表達式進一步檢查該異常以決定是否要對其進行處理。如果謂詞表達式返回 false,則繼續搜尋處理程式。

C#
Catch (ArgumentException e) if (e.ParamName == “…”)
{
}

 

異常篩選器要優於捕獲和重新引發(如下所述),因為篩選器將保留堆疊不受損壞。如果之後的處理程式轉儲堆疊,可以檢視到異常的原始來源,而不只是重新引發它的最後一個位置。異常篩選器表示式的一個常見用途是日誌記錄。可以建立一個始終返回 false 並輸出到日誌的謂詞函式,而且可以在異常通過時進行記錄,無需處理並重新引發它們。
可在 catch 塊中使用 throw 語句以重新引發已由 catch 語句捕獲的異常。下面的示例從 IOException 異常提取源資訊,然後向父方法引發異常。

複製程式碼

C#
catch (FileNotFoundException e)
{
    // FileNotFoundExceptions are handled here.
}
catch (IOException e)
{
    // Extract some information from this exception, and then 
    // throw it to the parent method.
    if (e.Source != null)
        Console.WriteLine("IOException source: {0}", e.Source);
    throw;
}

複製程式碼

 

你可以捕獲一個異常而引發一個不同的異常。執行此操作時,請指定作為內部異常捕獲的異常,如以下示例所示。

C#
catch (InvalidCastException e) 
{
    // Perform some action here, and then throw a new exception.
    throw new YourCustomException("Put your error message here.", e);
}

 

當指定的條件為 true 時,你還可以重新引發異常,如以下示例所示。

複製程式碼

C#

catch (InvalidCastException e)
{
    if (e.Data == null)
    {
        throw;
    }
    else
    {
        // Take some action.
    }
 }

複製程式碼

 

從 try 塊內,僅初始化在其中宣告的變數。否則,在完成執行塊之前,可能會出現異常。例如,在下面的程式碼示例中,變數 n 在 try 塊內部初始化。嘗試在 Write(n) 語句的 try 塊外部使用此變數將生成編譯器錯誤。

複製程式碼

C#
static void Main() 
{
    int n;
    try 
    {
        // Do not initialize this variable here.
        n = 123;
    }
    catch
    {
    }
    // Error: Use of unassigned local variable 'n'.
    Console.Write(n);
}

複製程式碼

 

=====

非同步方法中的異常
非同步方法由 async 修飾符標記,通常包含一個或多個 await 表示式或語句。await 表示式將 await 運算子應用於 Task 或 Task<TResult>。
當控制元件到達非同步方法中的 await 時,將掛起方法中的進度,直到所等待的任務完成。任務完成後,可以在方法中恢復執行。

應用了 await 的完成任務可能由於返回此任務的方法中存在未處理的異常而處於錯誤狀態。等待該任務引發異常。如果取消了返回任務的非同步程序,此任務最後也可能為已取消狀態。等待已取消的任務引發 OperationCanceledException。

若要捕獲異常,請在 try 塊中等待任務並在關聯的 catch 塊中捕獲異常。

任務可能處於錯誤狀態,因為等待的非同步方法中發生了多個異常。例如,任務可能是對 Task.WhenAll 呼叫的結果。當等待此類任務時,僅捕捉到其中一個異常,而且你無法預測將會捕獲到哪個異常。相關示例,請參見“示例”一節。

在下面的示例中,try 塊包含對可能引發異常的 ProcessString 方法的呼叫。 catch 子句包含只在螢幕上顯示一條訊息的異常處理程式。當從 MyMethod 內部呼叫 throw 語句時,系統將查詢 catch 語句並顯示訊息 Exception caught。

複製程式碼

C#
    class TryFinallyTest
{
    static void ProcessString(string s)
    {
        if (s == null)
        {
            throw new ArgumentNullException();
        }
    }

    static void Main()
    {
        string s = null; // For demonstration purposes.

        try
        {            
            ProcessString(s);
        }

        catch (Exception e)
        {
            Console.WriteLine("{0} Exception caught.", e);
        }
    }
}
    /*
    Output:
    System.ArgumentNullException: Value cannot be null.
       at TryFinallyTest.Main() Exception caught.
     * */

複製程式碼

 

在下面的示例中,使用了兩個 catch 塊,並捕獲到最先出現的最具體的異常。
若要捕獲最不具體的異常,你可以將 ProcessString 中的 throw 語句替換為以下語句:throw new Exception()。
如果將最不具體的 catch 塊置於示例中第一個,將顯示以下錯誤訊息:A previous catch clause already catches all exceptions of this or a super type ('System.Exception')。

複製程式碼

C#
class ThrowTest3
{
    static void ProcessString(string s)
    {
        if (s == null)
        {
            throw new ArgumentNullException();
        }
    }

    static void Main()
    {
        try
        {
            string s = null;
            ProcessString(s);
        }
        // Most specific:
        catch (ArgumentNullException e)
        {
            Console.WriteLine("{0} First exception caught.", e);
        }
        // Least specific:
        catch (Exception e)
        {
            Console.WriteLine("{0} Second exception caught.", e);
        }
    }
}
/*
 Output:
 System.ArgumentNullException: Value cannot be null.
 at Test.ThrowTest3.ProcessString(String s) ... First exception caught.
*/

複製程式碼

 

下面的示例闡釋非同步方法的異常處理。若要捕獲非同步任務引發的異常,將 await 表示式置於 try 塊中,並在 catch 塊中捕獲該異常。
將演示異常處理的示例中的 Throw New Exception 行取消註釋。 任務的 IsFaulted 屬性設定為 True,任務的 Exception.InnerException 屬性設定為異常,並在 catch 塊中捕獲該異常。
取消註釋 throw new OperationCancelledException 行以演示在取消非同步程序時發生的情況。任務的 IsCanceled 屬性設定為 true,並在 catch 塊中捕獲異常。在某些不適用於此示例的情況下,任務的 IsFaulted 屬性設定為 true 且 IsCanceled 設定為 false。

複製程式碼

C#
public async Task DoSomethingAsync()
{
    Task<string> theTask = DelayAsync();

    try
    {
        string result = await theTask;
        Debug.WriteLine("Result: " + result);
    }
    catch (Exception ex)
    {
        Debug.WriteLine("Exception Message: " + ex.Message);
    }
    Debug.WriteLine("Task IsCanceled: " + theTask.IsCanceled);
    Debug.WriteLine("Task IsFaulted:  " + theTask.IsFaulted);
    if (theTask.Exception != null)
    {
        Debug.WriteLine("Task Exception Message: "
            + theTask.Exception.Message);
        Debug.WriteLine("Task Inner Exception Message: "
            + theTask.Exception.InnerException.Message);
    }
}

private async Task<string> DelayAsync()
{
    await Task.Delay(100);

    // Uncomment each of the following lines to
    // demonstrate exception handling.

    //throw new OperationCanceledException("canceled");
    //throw new Exception("Something happened.");
    return "Done";
}

// Output when no exception is thrown in the awaited method:
//   Result: Done
//   Task IsCanceled: False
//   Task IsFaulted:  False

// Output when an Exception is thrown in the awaited method:
//   Exception Message: Something happened.
//   Task IsCanceled: False
//   Task IsFaulted:  True
//   Task Exception Message: One or more errors occurred.
//   Task Inner Exception Message: Something happened.

// Output when a OperationCanceledException or TaskCanceledException
// is thrown in the awaited method:
//   Exception Message: canceled
//   Task IsCanceled: True
//   Task IsFaulted:  False

複製程式碼

 

下面的示例闡釋了在多個任務可能導致多個異常的情況中的異常處理。 try 塊等待由 Task.WhenAll 的呼叫返回的任務。應用了 WhenAll 的三個任務完成後,該任務完成。
三個任務中的每一個都會導致異常。 catch 塊迴圈訪問異常,這些異常位於由 Task.WhenAll 返回的任務的 Exception.InnerExceptions 屬性中。

複製程式碼

C#
public async Task DoMultipleAsync()
{
    Task theTask1 = ExcAsync(info: "First Task");
    Task theTask2 = ExcAsync(info: "Second Task");
    Task theTask3 = ExcAsync(info: "Third Task");

    Task allTasks = Task.WhenAll(theTask1, theTask2, theTask3);

    try
    {
        await allTasks;
    }
    catch (Exception ex)
    {
        Debug.WriteLine("Exception: " + ex.Message);
        Debug.WriteLine("Task IsFaulted: " + allTasks.IsFaulted);
        foreach (var inEx in allTasks.Exception.InnerExceptions)
        {
            Debug.WriteLine("Task Inner Exception: " + inEx.Message);
        }
    }
}

private async Task ExcAsync(string info)
{
    await Task.Delay(100);

    throw new Exception("Error-" + info);
}

// Output:
//   Exception: Error-First Task
//   Task IsFaulted: True
//   Task Inner Exception: Error-First Task
//   Task Inner Exception: Error-Second Task
//   Task Inner Exception: Error-Third Task