Cấp bậc tác giả:

TRAINING

Sử dụng Try... Catch..., Finally!

Được viết bởi QuangIT ngày 10/06/2014 lúc 02:52 PM
Xử lý lỗi là phần quan trọng đối với công việc của lập trình viên .NET Framework. Cung cấp một số công cụ rất mạnh để xử lý các lỗi một cách tương đối dễ dàng.
  • 0
  • 16624
Tải tệp tin: Click ở đây

Sử dụng Try... Catch..., Finally!

Giới thiệu

Xử lý lỗi là phần quan trọng đối với công việc của lập trình viên .NET Framework. Cung cấp một số công cụ rất mạnh để xử lý các lỗi một cách tương đối dễ dàng. 
Một trong những công cụ này là Try... Catch... Finally... . Tuy nhiên, tôi thấy nhiều bạn viết sai khá nhiều khi sử dụng Try ... Catch ... Finally ... không chỉ đối với lập trình viên mới bắt đầu, mà còn cả các lập trình viên kinh nghiệm lâu năm. 
Có rất nhiều cuốn sách và ​​thảo luận về lỗi xử lý trong .NET .Nhưng nhiều người không có cái nhìn tổng quan đối về khối Try... Catch... Finally...
Với bài viết này, tôi hy vọng các nhà phát triển phần mềm sẽ có cái nhìn sử dụng hợp lý và chi tiết về khối Try ... Catch ... Finally ...

Các ví dụ

Đối với bài viết này, tôi đã thực hiện ứng dụng ví dụ nhỏ cho mục đích sử dụng khác nhau của Try ... Catch ... Finally .... Ví dụ dễ sử dụng và gỡ lỗi. 
Ví dụ bao gồm Form duy nhất với một số nút trên đó. Mỗi nút thể hiện việc sử dụng cụ thể Try ... Catch ... Finally ...  và sửa lỗi bằng cách sử dụng các điểm ngắt để hiểu đầy đủ. Lưu ý rằng mã chính không thực sự làm. Nó chỉ đơn giản là ném ngoại lệ và xử lý chúng.

UsingTryCatchFinally.jpg

Ví dụ được thực hiện trên Visual Studio 2010 Express Phiên bản sử dụng NET Framework 4.0.. Tuy nhiên, tất cả các mã có thể dễ dàng được sử dụng trong bất kỳ ứng dụng .NET 3.5.

Một số vấn đề cơ bản về ngoại lệ

Luôn luôn có lỗi khi bạn xây dựng ứng dụng phần mềm. Có thể kết nối đến cơ sở dữ liệu thất bại, hoặc mở tập tin mà không tồn tại trên máy tính của người sử dụng hay người dùng không có quyền truy cập. Nếu lỗi xảy ra, .NET Framework tập hợp thông tin sai và ném ngoại lệ. . NET Framework có nhiều kiểu ngoại lệ, chẳng hạn như FileNotFoundException, IndexOutOfRangeException và SqlException. Một số Exception các lớp cung cấp thông tin cụ thể về những gì vừa xảy ra. Ví dụ, SqlException chứa thông tin về mức độ nghiêm trọng của SqlError .

Ngoại lệ được ném ra, tất cả chúng đều kế thừa từ lớp System.Exception. Khi Exception được ném ra bởi NET Framework, nó sẽ tự động tìm kiếm khối Catch đầu tiên (chứa trong khối Try ... Catch ...) trong ngăn xếp. Nếu ngăn xếp không chứa bất kỳ Catch, ngoại lệ không được quản lý xảy ra. Nó sẽ cung cấp cho người dùng cuối rằng ngoại lệ không được quản lý xảy ra và chúng có thể tiếp tục và bỏ qua lỗi hoặc thoát khỏi ứng dụng. Trong trường hợp tốt nhất, ứng dụng của bạn được đóng trong hai cách.
Là lập trình viên, bạn thường không muốn người dùng thấy thông báo như vậy. Vì vậy, điều quan trọng là luôn luôn thực hiện xử lý lỗi trong mã của bạn bằng cách sử dụng khối Try ... Catch ....

Thử ví dụ

Khi bạn mở ví dụ dự án, bạn sẽ thấy Form với nhiều nút. 
Tôi biết các nút lớn màu đỏ trông hấp dẫn, nhưng chúng ta không nhấn nó ngay lập tức. Thay vào đó, đầu tiên xây dựng dự án. Bây giờ hãy vào thư mục gỡ rối của bạn (thường nằm trong thư mục giải pháp của bạn) và chạy file thực thi. Bây giờ bạn có thể nhấn nút lớn màu đỏ. Mà không nhìn rất tốt, đúng không? 
Bây giờ, nhấn bất kỳ khác của các nút (trừ Close) và nhận thấy sự khác biệt. Quay trở lại các tập tin dự án một lần nữa. Trước khi chạy ứng dụng, tôi muốn bạn nhấn phím tắt Ctrl + Alt + E trong Visual Studio. Điều này sẽ hiển thị hộp thoại ngoại lệ. Hãy chắc chắn rằng cả hai hộp kiểm tra sau 'Common Language Runtime ngoại lệ' được kiểm tra. Điều này sẽ đảm bảo rằng bạn đi vào chế độ gỡ lỗi bất cứ khi nào một ngoại lệ được ném trong mã của bạn. Chúng tôi đề nghị bạn bước đầy đủ thông qua các mã của nút bất kỳ bằng cách sử dụng Breakpoints và F8 để thực hiện theo các con đường ngoại lệ thực hiện khi đối phó với Try ... Catch ... Finally khối.

Try ... Catch ...

Mở Project và nhấn nút đầu tiên trên Form, với Try ... Catch .... nhảy qua mã nguồn.

Private Sub btnSimpleTryCatch_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles btnSimpleTryCatch.Click
        Try
            ' Một vài dòng code ở đây
            ' Lỗi xảy ra!
            Throw New System.Exception("Một lỗi không mong muốn đã xảy ra")
            'Một số mã thêm ở đây ... Chúng sẽ không được thực thi nếu ngoại lệ xảy ra.
        Catch ex As Exception
            ' Xử lý các trường hợp ngoại lệ.
            MessageBox.Show(ex.Message, Me.Text, _
        MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

Try... Catch... Finally...

Chúng ta hãy chuyển sang nút thứ hai trên Form. Click vào và thấy con trỏ đang chờ đợi! Sau vài giây,...

Private Sub btnSimpleTryCatchFinally_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles btnSimpleTryCatchFinally.Click
        ' Con trỏ chuyển sang chế độ chờ.
        Me.Cursor = Cursors.WaitCursor
        Try
            ' Một số mã ở đây ...
            ' Thời gian chờ đợi!
            Threading.Thread.Sleep(5000)
            ' Lỗi xảy ra!
            Throw New System.Exception("Xảy ra lỗi không mong muốn.")
            ' Một số mã thêm ở đây ...
        Catch ex As Exception
            ' Xử lý các trường hợp ngoại lệ.
            MessageBox.Show(ex.Message, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
        Finally
            ' Hãy chắc chắn rằng con trỏ được thiết lập trở lại mặc định!
            Me.Cursor = Cursors.Default
        End Try
    End Sub

Nhiều Catches

Trong một số trường hợp, bạn có thể muốn xử lý một số ngoại lệ khác biệt. Ví dụ sau đây cung cấp giải thích của nhiều Catch trong khối Try... Catch... . Ví dụ, đang cố để mở một tập tin trên máy tính của người dùng. Điều gì có thể xảy ra?. Có thể là thư mục của tập tin bạn đang cố mở không tồn tại, có thể tập tin không tồn tại, có thể người dùng không có quyền để mở file hoặc có thể một cái gì đó hoàn toàn bất ngờ xảy ra. Trong trường hợp này, bạn có thể sử dụng nhiều catches, như mã sau đây: 

Private Sub btnMultipleCatches_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles btnMultipleCatches.Click
        Try
            ' Một số mã ở đây ...
            ' Hãy chỉ ra rằng chúng ta đang cố mở một tập tin ở đây.
            ' Lỗi xảy ra!
            Dim rand As New Random
            If rand.Next(2) = 1 Then
                Throw New IO.FileNotFoundException_
        ("Tập tin bạn đang cố gắng mở không được tìm thấy. ")
            Else
                Throw New System.Exception("Có lỗi xảy ra không rõ.")
            End If
            ' Một số mã thêm ở đây ...
        Catch dirEx As IO.DirectoryNotFoundException
            ' xử lý DirectoryNotFoundException ở đây.
            MessageBox.Show(dirEx.Message, "Thư mục không tìm thấy", _
        MessageBoxButtons.OK, MessageBoxIcon.Error)
        Catch fileEx As IO.FileNotFoundException
            ' Xử lý FileNotFoundException ở đây.
            MessageBox.Show(fileEx.Message, "File not found", _
        MessageBoxButtons.OK, MessageBoxIcon.Error)
        Catch ioEx As IO.IOException
            ' Xử lý ngoại lệ IO ở đây.
            MessageBox.Show(ioEx.Message, "IO exception", _
        MessageBoxButtons.OK, MessageBoxIcon.Error)
        Catch ex As Exception
            ' Xử lý bất kỳ ngoại lệ IO khác ở đây.
            MessageBox.Show(ex.Message, "Ngoại lệ Không biết", _
        MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

Lưu ý bằng cách nào ngoại lệ được tạo ra sử dụng lớp Ramdom. 50% thời gian, chúng ta sẽ nhận được FileNotFoundException và 50% thời gian, chúng ta sẽ có ngoại lệ cụ thể. 
Tại thời điểm này, bạn có thể muốn bỏ chọn hộp kiểm mà bạn kiểm tra ở đầu bài viết này bằng cách sử dụng Control + Alt + E và nhấn nút 'Multiple catches' vài lần để xem nó như thế nào

Trường hợp ngoại lệ từ phương thức Deeper

Quan niệm sai lầm phổ biến về Try... Catch ... là khối mã duy nhất. Điều này không đúng trong nhiều trường hợp.

Private Sub btnExceptionsFromDeeperMethods_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles btnExceptionsFromDeeperMethods.Click
        Try
            Dim mm As New ManyMethods
            ' This method goes into three other methods!
            mm.GoIntoDeeperMethods()
        Catch ex As Exception
            MessageBox.Show(ex.Message & Environment.NewLine & _
                            "The method which threw me was: " & ex.TargetSite.Name, _
                            Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    Public Sub GoIntoDeeperMethods()
        B() ' Goes into B, which goes into C, which goes into ExceptionMethod,
            ' which throws an error.
        MessageBox.Show("You will never see me!", "Some deeper method", _
        MessageBoxButtons.OK, MessageBoxIcon.Information)
        AA() ' Will never be executed.
        AB() ' Will never be executed.
    End Sub

    ' Method B, C, AA and AB show MessageBoxes,
         ' but only after eventually calling the ExceptionMethod.
    ' The MessageBoxes will therefore never be prompted.

    Private Sub ExceptionMethod()
        ' Some code here...
        ' Oops! An error occurs!
        Throw New System.Exception("I am coming from way down here!") ' This returns
        ' to the first Catch block, in the case in the button Event Handler.
        ' Some code here...
    End Sub

Finally trong phương thức Deeper

Private Sub btnFinallyInDeeperMethods_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles btnFinallyInDeeperMethods.Click
        Try
            Dim mm As New ManyMethods
            ' This method goes into four other methods!
            mm.GoIntoDeeperMethodsWithFinally()
        Catch ex As Exception
            MessageBox.Show(ex.Message & Environment.NewLine & _
                            "The method which threw me was: " & ex.TargetSite.Name, _
                            Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    Public Sub GoIntoDeeperMethodsWithFinally()
        Try
            ' This will eventually throw an exception.
            GoIntoDeeperMethods()
        Finally
            ' This code will ALWAYS be executed.
            MessageBox.Show("You will always see me!", _
        "Finally", MessageBoxButtons.OK, MessageBoxIcon.Information)
        End Try
    End Sub

Ném nhiều ngoại lệ nhiều lần

Private Sub btnHandlingAnExceptionMultipleTimes_Click_
    (ByVal sender As System.Object, ByVal e As System.EventArgs) _
    Handles btnHandlingAnExceptionMultipleTimes.Click
        Try
            Dim mm As New ManyMethods
            ' This method goes into four other methods!
            mm.GoIntoDeeperMethodsWithCatch()
        Catch ex As Exception
            MessageBox.Show(ex.Message & Environment.NewLine & _
                            "The method which threw me was: " & _
             ex.TargetSite.Name & Environment.NewLine & _
                            "The method which initially threw me was: _
             " & ex.InnerException.TargetSite.Name, _
                            Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    Public Sub GoIntoDeeperMethodsWithCatch()
        Try
            ' This will eventually throw an exception.
            GoIntoDeeperMethods()
        Catch ex As Exception
            MessageBox.Show("Do some specific error handling here...", _
        "Some deeper method", MessageBoxButtons.OK, MessageBoxIcon.Information)
            ' Rethrow the Exception to the form so the form can handle the user interface.
            Dim newEx As New System.Exception("I am rethrown!", ex)
            Throw newEx
        End Try
    End Sub

Lồng Try... Catch... Finally...

Private Sub btnNestedTryCatch_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles btnNestedTryCatch.Click
        Try
            ' Some code here...
            Try
                ' Some more code here...
                Dim table As New DataTable
                Try
                    ' Some more code here...
                    ' Oops! An error occurs!
                    Throw New System.Exception("I come from the third nested try.")
                    ' No Catch here, only a finally.
                Finally
                    ' This code will always execute.
                    table.Dispose()
                End Try
            Catch ex As Exception
                MessageBox.Show(ex.Message & Environment.NewLine & _
        " I was handled in the second Try... Catch... block.", _
                                Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
            End Try
        Catch ex As Exception
            MessageBox.Show(ex.Message & Environment.NewLine & _
        " I was handled in the first Try... Catch... block.", _
                            Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

Using... End Using

Private Sub btnUsingEndUsing_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles btnUsingEndUsing.Click
        Dim table1 As New DataTable
        Try
            ' Some code here...
        Finally
            table1.Dispose()
        End Try

        ' The above code actually does the same as this code!
        ' The Using... End Using block can be used with any object that
        ' implements IDisposable and makes sure that your object is disposed
        ' of, no matter what happens.
        Using table2 As New DataTable
            ' Some code here...
        End Using

        MessageBox.Show("This button does not actually do something." _
    & Environment.NewLine & "Check the source code :)", _
                        Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
    End Sub

Tóm tắt

Private Sub btnToSumItUp_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles btnToSumItUp.Click
        Me.Cursor = Cursors.WaitCursor
        Try
            DoSomeSqlStuff()
            ' This is an alternative block of code that does the same
            ' as DoSomeSqlStuff, but looks quite differently.
            ' AlternativeDoSomeSqlStuff()
        Catch sqlEx As SqlClient.SqlException
            MessageBox.Show(sqlEx.Message, "SQL Exception", _
        MessageBoxButtons.OK, MessageBoxIcon.Error)
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Unknown exception", _
        MessageBoxButtons.OK, MessageBoxIcon.Error)
        Finally
            ' Make sure the cursor is set back to default!
            Me.Cursor = Cursors.Default
        End Try
    End Sub

    Private Sub DoSomeSqlStuff()
        Using connection As New SqlClient.SqlConnection_
    ("Data Source=SomeServer;Initial Catalog=SomeDB;Integrated Security=True")
            Using cmd As New SqlClient.SqlCommand_
        ("SELECT * FROM SomeTable", connection)
                connection.Open()
                Try
                    Using reader As SqlClient.SqlDataReader = cmd.ExecuteReader
                        While reader.Read
                            ' Do something... This will never happen :)
                        End While
                    End Using ' SqlReader is disposed.
                Finally
                    ' Always close the connection!
                    connection.Close()
                End Try
            End Using ' SqlCommand is disposed.
        End Using ' SqlConnection is disposed.
    End Sub

Private Sub AlternativeDoSomeSqlStuff()
        Dim connection As New SqlClient.SqlConnection_
    ("Data Source=SomeServer;Initial Catalog=SomeDB;Integrated Security=True")
        Dim cmd As New SqlClient.SqlCommand("SELECT * FROM SomeTable", connection)
        Try
            connection.Open()
            Using reader As SqlClient.SqlDataReader = cmd.ExecuteReader
                While reader.Read
                    ' Do something... This will never happen :)
                End While
            End Using ' SqlReader is disposed.
        Finally
            connection.Close()
            connection.Dispose()
            cmd.Dispose()
        End Try
    End Sub

Nguồn bài viết: DOTNET.VN

BÌNH LUẬN BÀI VIẾT

Bài viết mới nhất

LIKE BOX

Bài viết được xem nhiều nhất

HỌC HTML