Xử lý lỗi
Nội dung bài · 5 mục
- 1.Khái niệm
- 2.Ví dụ
- 3.Thử ngay
- 4.Lỗi hay gặp
- 5.Tóm tắt
Oracle tắt, mạng rớt, dữ liệu vi phạm ràng buộc: sớm muộn app cũng gặp lỗi. Không xử lý thì nhân viên thấy một hộp lỗi dài, khó hiểu của .NET. Bài này giúp app báo lỗi dễ hiểu và vẫn chạy tiếp.
Khái niệm
🚨 Application.ThreadException: event nhận mọi exception chưa được bắt trong các handler của giao diện, kể cả handler async void.
App xử lý lỗi theo hai tầng, giống khoá ASP.NET Core. Lỗi lường trước được
thì bắt tại chỗ bằng try/catch, như bài Exception của khoá C# Core. Lỗi
còn lại đi về một chỗ chung, như bài Xử lý lỗi tập trung.
Ví dụ
Bắt lỗi kết nối ngay trong LoadAsync của bài trước:
using Oracle.ManagedDataAccess.Client;
// Trong MainForm, thay LoadAsync cũ
private async Task LoadAsync()
{
try
{
_source.DataSource =
await _store.InStockAsync();
}
catch (OracleException)
{
MessageBox.Show(
"Không kết nối được database. "
+ "Kiểm tra Oracle rồi thử lại.",
"Lỗi kết nối",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}Chỗ chung cho các lỗi còn lại đặt trong Main, trước Application.Run:
Application.ThreadException += (sender, e) =>
{
MessageBox.Show(
"Có lỗi xảy ra: " + e.Exception.Message,
"Lỗi",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
};OracleExceptionnằm trongOracle.ManagedDataAccess.Client, cùng thư viện vớiOracleCommandở bài SQL injection. EF Core ném thẳng nó ra khi không kết nối được.- Ở đây chỉ bắt
OracleException. Lỗi loại khác đi tiếp ra ngoài và rơi vàoThreadException. - Handler của
ThreadExceptionhiện thông báo, sau đó app vẫn chạy tiếp. MessageBoxIcon.Errorthêm biểu tượng lỗi màu đỏ vào hộp thông báo.
Thử ngay
Tắt Oracle bằng docker stop oracle, rồi chạy app.
Đoán trước khi chạy: app sẽ sập, bị treo hay hiện gì?
Xem kết quả
Vài giây sau, hộp "Lỗi kết nối" hiện ra:
"Không kết nối được database. Kiểm tra Oracle rồi thử lại."
Bấm OK: cửa sổ kho vẫn mở, lưới trống.InStockAsync thử kết nối vài giây, không được thì ném OracleException
với mã ORA-50201. catch bắt được nên app không sập. Chạy
docker start oracle rồi mở lại app là có dữ liệu.
Lỗi hay gặp
catch (Exception) rồi bỏ trống. Như bài Exception của khoá C# Core, mọi
lỗi đều bị giấu đi, kể cả lỗi do code sai. Nhân viên thấy lưới trống mà không biết vì sao.
// SAI — lỗi gì cũng im lặng
try
{
_source.DataSource =
await _store.InStockAsync();
}
catch (Exception)
{
}// ĐÚNG — chỉ bắt lỗi biết cách xử lý, và báo ra
try
{
_source.DataSource =
await _store.InStockAsync();
}
catch (OracleException)
{
MessageBox.Show("Không kết nối được database.");
}Tóm tắt
- Lỗi lường trước được thì
try/catchđúng loại, nhưOracleException. Application.ThreadExceptionlà chỗ chung cho mọi lỗi chưa được bắt.- Báo lỗi bằng
MessageBoxvới lời dễ hiểu, app vẫn chạy tiếp. - Không
catchrồi bỏ trống.
Tự kiểm tra
0/3 câuHandler async void của nút Lưu ném exception sau một lệnh await, không có try/catch. Main đã gắn Application.ThreadException. Chuyện gì xảy ra?
Nên bắt OracleException ở đâu?
Vì sao catch (Exception) { } bỏ trống là lỗi?