LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開(kāi)發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

讓你的Winform程序堅(jiān)如磐石:全局異常捕獲實(shí)戰(zhàn)

admin
2025年2月5日 11:28 本文熱度 43

一、引言:程序也會(huì) “鬧脾氣”

家人們,咱就是說(shuō),有沒(méi)有這樣的經(jīng)歷:滿心歡喜打開(kāi)一個(gè)桌面應(yīng)用程序,準(zhǔn)備大干一場(chǎng),結(jié)果操作沒(méi)幾下,突然彈出一個(gè) “程序已停止工作” 的窗口 ,瞬間讓人心態(tài)崩了!這其實(shí)就是程序在運(yùn)行過(guò)程中遇到了未處理的異常,直接 “撂挑子” 不干啦。

對(duì)于咱們開(kāi)發(fā) Winform 程序的小伙伴來(lái)說(shuō),這種情況更是不能容忍。一個(gè)小小的異常,可能就會(huì)讓用戶對(duì)我們的軟件失去信心。所以,今天就來(lái)和大家好好嘮嘮 Winform 程序中的全局異常捕獲處理,讓程序變得更 “堅(jiān)強(qiáng)”,不再輕易 “鬧脾氣”!

二、認(rèn)識(shí)異常:程序中的 “小怪獸”

(一)什么是異常

在程序的世界里,異常就像是突然冒出來(lái)的 “小怪獸” ,阻擋程序順利運(yùn)行。簡(jiǎn)單來(lái)說(shuō),異常就是程序在執(zhí)行過(guò)程中出現(xiàn)的錯(cuò)誤情況。當(dāng)程序遇到一些不符合預(yù)期的條件,比如找不到文件、無(wú)法進(jìn)行類型轉(zhuǎn)換,或者內(nèi)存不足時(shí),就會(huì)拋出異常。這些異常如果不加以處理,就會(huì)導(dǎo)致程序的運(yùn)行中斷,就像汽車在行駛過(guò)程中突然爆胎,不得不停下來(lái)一樣。

(二)異常的類型和危害

在 Winform 開(kāi)發(fā)中,常見(jiàn)的異常類型有很多。比如,空引用異常(NullReferenceException),這是最常見(jiàn)的異常之一。當(dāng)你試圖訪問(wèn)一個(gè)值為 null 的對(duì)象的屬性或方法時(shí),就會(huì)拋出這個(gè)異常。想象一下,你手里拿著一個(gè)空盒子,卻想從里面拿出東西,肯定是拿不到的,程序就會(huì)拋出異常來(lái)提醒你。又比如類型轉(zhuǎn)換異常(InvalidCastException),當(dāng)你嘗試將一個(gè)對(duì)象轉(zhuǎn)換為不兼容的類型時(shí),就會(huì)出現(xiàn)這個(gè)問(wèn)題。就好比你把蘋(píng)果當(dāng)成橙子,強(qiáng)行要把蘋(píng)果榨成橙汁,這顯然是不行的 。

這些異常如果不處理,危害可不小。最直接的就是導(dǎo)致程序崩潰,用戶正在使用軟件,突然程序就關(guān)閉了,這體驗(yàn)感簡(jiǎn)直太差了。還可能導(dǎo)致數(shù)據(jù)丟失,比如用戶正在輸入重要信息,結(jié)果因?yàn)楫惓3绦虮罎ⅲ拜斎氲臄?shù)據(jù)沒(méi)保存下來(lái),用戶肯定會(huì)很生氣。所以,為了讓程序穩(wěn)定運(yùn)行,給用戶提供良好的體驗(yàn),我們必須要處理這些異常。

三、全局異常捕獲:給程序穿上 “防護(hù)服”

(一)什么是全局異常捕獲

在 Winform 程序中,全局異常捕獲就像是給程序安裝了一個(gè) “超級(jí)護(hù)盾” ,它可以捕獲整個(gè)應(yīng)用程序中未處理的異常。簡(jiǎn)單來(lái)說(shuō),就是不管程序的哪個(gè)部分出現(xiàn)了異常,只要沒(méi)有被局部的 try - catch 塊捕獲,全局異常捕獲機(jī)制就會(huì)發(fā)揮作用,把這些 “漏網(wǎng)之魚(yú)” 異常給抓住。

(二)為什么要使用全局異常捕獲

  1. 提高程序穩(wěn)定性
    :當(dāng)程序遇到異常時(shí),如果沒(méi)有全局異常捕獲,很可能就會(huì)直接崩潰。而有了全局異常捕獲,就可以避免程序因?yàn)橐恍┮馔獾漠惓6蝗唤K止,讓程序更加穩(wěn)定地運(yùn)行。就好比給房子加固了地基,房子就不容易因?yàn)橐稽c(diǎn)小震動(dòng)而倒塌。
  1. 增強(qiáng)用戶體驗(yàn)
    :想象一下,用戶在使用我們開(kāi)發(fā)的 Winform 程序時(shí),如果頻繁遇到程序崩潰的情況,肯定會(huì)對(duì)這個(gè)程序失去信心。通過(guò)全局異常捕獲,我們可以在程序出現(xiàn)異常時(shí),給用戶一個(gè)友好的提示,比如 “很抱歉,程序出現(xiàn)了一點(diǎn)小問(wèn)題,請(qǐng)稍后再試” ,而不是讓用戶看到一個(gè)莫名其妙的錯(cuò)誤窗口,這樣可以大大提升用戶體驗(yàn)。
  1. 方便錯(cuò)誤排查
    :全局異常捕獲不僅可以捕獲異常,還可以記錄異常的詳細(xì)信息,比如異常發(fā)生的時(shí)間、異常類型、異常信息以及堆棧調(diào)用等。這些信息對(duì)于我們開(kāi)發(fā)人員來(lái)說(shuō),就像是破案的線索,可以幫助我們快速定位和解決問(wèn)題。當(dāng)程序出現(xiàn)問(wèn)題時(shí),我們可以根據(jù)這些記錄的異常信息,迅速找到問(wèn)題所在,提高開(kāi)發(fā)效率。

四、實(shí)戰(zhàn)演練:打造異常捕獲 “神器”

(一)前期準(zhǔn)備

在開(kāi)始實(shí)戰(zhàn)之前,先確保我們的開(kāi)發(fā)環(huán)境已準(zhǔn)備就緒。這里我使用的是 Visual Studio 2022 ,它功能強(qiáng)大,能為我們的開(kāi)發(fā)工作提供很多便利。.NET Framework 版本為 4.8,這個(gè)版本兼容性較好,能滿足大多數(shù) Winform 項(xiàng)目的需求。如果你還沒(méi)有安裝這些工具,可以前往微軟官方網(wǎng)站進(jìn)行下載安裝。

(二)關(guān)鍵代碼實(shí)現(xiàn)

  1. UI 線程異常捕獲

在 Winform 中,UI 線程負(fù)責(zé)處理用戶界面的交互和更新。為了捕獲 UI 線程中的異常,我們可以使用 Application.ThreadException 事件。下面是一段示例代碼:

// 設(shè)置應(yīng)用程序處理異常方式:ThreadException處理

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

// 處理UI線程異常

Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);

在這段代碼中,Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException) 這行代碼設(shè)置了應(yīng)用程序處理未處理異常的模式,這里設(shè)置為捕獲異常。Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException) 則是為Application.ThreadException事件添加了一個(gè)處理程序,當(dāng) UI 線程中出現(xiàn)未處理的異常時(shí),就會(huì)調(diào)用Application_ThreadException方法。

下面是Application_ThreadException方法的具體實(shí)現(xiàn):

static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)

{

string str = "";

string strDateInfo = "出現(xiàn)應(yīng)用程序未處理的異常:" + DateTime.Now.ToString() + "\r\n";

Exception error = e.Exception as Exception;

if (error!= null)

{

str = string.Format(strDateInfo + "異常類型:{0}\r\n異常消息:{1}\r\n異常信息:{2}\r\n",

error.GetType().Name, error.Message, error.StackTrace);

}

else

{

str = string.Format("應(yīng)用程序線程錯(cuò)誤:{0}", e);

}

// 寫(xiě)日志

WriteLog.WriteErrLog(str);

MessageBox.Show("發(fā)生致命錯(cuò)誤,請(qǐng)及時(shí)聯(lián)系作者!", "系統(tǒng)錯(cuò)誤", MessageBoxButtons.OK, MessageBoxIcon.Error);

}

在這個(gè)方法中,首先獲取當(dāng)前時(shí)間,構(gòu)建異常信息的開(kāi)頭部分。然后通過(guò)e.Exception獲取異常對(duì)象,進(jìn)一步獲取異常類型、消息和堆棧跟蹤信息,并將這些信息格式化為一個(gè)字符串。接著調(diào)用WriteLog.WriteErrLog(str)方法將異常信息寫(xiě)入日志文件,方便后續(xù)排查問(wèn)題。最后使用MessageBox.Show方法彈出一個(gè)提示框,告知用戶程序出現(xiàn)了錯(cuò)誤。

  1. 非 UI 線程異常捕獲

對(duì)于非 UI 線程中的異常,我們可以使用 AppDomain.CurrentDomain.UnhandledException 事件來(lái)捕獲。代碼如下:

// 處理非UI線程異常

AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

同樣,這里為AppDomain.CurrentDomain.UnhandledException事件添加了一個(gè)處理程序CurrentDomain_UnhandledException。下面是該方法的實(shí)現(xiàn):

static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)

{

string str = "";

Exception error = e.ExceptionObject as Exception;

string strDateInfo = "出現(xiàn)應(yīng)用程序未處理的異常:" + DateTime.Now.ToString() + "\r\n";

if (error!= null)

{

str = string.Format(strDateInfo + "Application UnhandledException:{0};\\n\\r堆棧信息:{1}", error.Message, error.StackTrace);

}

else

{

str = string.Format("Application UnhandledError:{0}", e);

}

// 寫(xiě)日志

WriteLog.WriteErrLog(str);

MessageBox.Show("發(fā)生致命錯(cuò)誤,請(qǐng)停止當(dāng)前操作并及時(shí)聯(lián)系作者!", "系統(tǒng)錯(cuò)誤", MessageBoxButtons.OK, MessageBoxIcon.Error);

}

這個(gè)方法和 UI 線程異常捕獲的方法類似,也是獲取異常信息,記錄日志并彈出提示框。不同的是,這里通過(guò)e.ExceptionObject獲取異常對(duì)象,因?yàn)榉?UI 線程的異常處理方式和 UI 線程略有不同。

  1. 異常信息處理

在捕獲到異常后,對(duì)異常信息進(jìn)行整理是很重要的一步。我們可以獲取異常的類型、消息、堆棧跟蹤等信息。例如,在前面的代碼中,通過(guò)error.GetType().Name獲取異常類型的名稱,error.Message獲取異常的具體消息,error.StackTrace獲取異常發(fā)生時(shí)的堆棧跟蹤信息。這些信息可以幫助我們快速定位問(wèn)題所在,比如異常是在哪個(gè)類、哪個(gè)方法中發(fā)生的 。通過(guò)將這些信息記錄到日志文件中,我們可以在程序出現(xiàn)問(wèn)題后,通過(guò)查看日志來(lái)分析問(wèn)題,從而更好地解決問(wèn)題。

(三)完整代碼示例

下面是一個(gè)完整的包含全局異常捕獲處理的 Winform 程序代碼示例:

using System;

using System.Windows.Forms;

using System.IO;

using System.Text;

namespace WinFormExceptionHandling

{

static class Program

{

/// <summary>

/// 應(yīng)用程序的主入口點(diǎn)。

/// </summary>

[STAThread]

static void Main()

{

try

{

// 設(shè)置應(yīng)用程序處理異常方式:ThreadException處理

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

// 處理UI線程異常

Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);

// 處理非UI線程異常

AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

Application.EnableVisualStyles();

Application.SetCompatibleTextRenderingDefault(false);

Application.Run(new Form1());

}

catch (Exception ex)

{

string str = "";

string strDateInfo = "出現(xiàn)應(yīng)用程序未處理的異常:" + DateTime.Now.ToString() + "\r\n";

if (ex!= null)

{

str = string.Format(strDateInfo + "異常類型:{0}\r\n異常消息:{1}\r\n異常信息:{2}\r\n",

ex.GetType().Name, ex.Message, ex.StackTrace);

}

else

{

str = string.Format("應(yīng)用程序線程錯(cuò)誤:{0}", ex);

}

// 寫(xiě)日志

WriteLog.WriteErrLog(str);

MessageBox.Show("發(fā)生致命錯(cuò)誤,請(qǐng)及時(shí)聯(lián)系作者!", "系統(tǒng)錯(cuò)誤", MessageBoxButtons.OK, MessageBoxIcon.Error);

}

}

static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)

{

string str = "";

string strDateInfo = "出現(xiàn)應(yīng)用程序未處理的異常:" + DateTime.Now.ToString() + "\r\n";

Exception error = e.Exception as Exception;

if (error!= null)

{

str = string.Format(strDateInfo + "異常類型:{0}\r\n異常消息:{1}\r\n異常信息:{2}\r\n",

error.GetType().Name, error.Message, error.StackTrace);

}

else

{

str = string.Format("應(yīng)用程序線程錯(cuò)誤:{0}", e);

}

// 寫(xiě)日志

WriteLog.WriteErrLog(str);

MessageBox.Show("發(fā)生致命錯(cuò)誤,請(qǐng)及時(shí)聯(lián)系作者!", "系統(tǒng)錯(cuò)誤", MessageBoxButtons.OK, MessageBoxIcon.Error);

}

static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)

{

string str = "";

Exception error = e.ExceptionObject as Exception;

string strDateInfo = "出現(xiàn)應(yīng)用程序未處理的異常:" + DateTime.Now.ToString() + "\r\n";

if (error!= null)

{

str = string.Format(strDateInfo + "Application UnhandledException:{0};\\n\\r堆棧信息:{1}", error.Message, error.StackTrace);

}

else

{

str = string.Format("Application UnhandledError:{0}", e);

}

// 寫(xiě)日志

WriteLog.WriteErrLog(str);

MessageBox.Show("發(fā)生致命錯(cuò)誤,請(qǐng)停止當(dāng)前操作并及時(shí)聯(lián)系作者!", "系統(tǒng)錯(cuò)誤", MessageBoxButtons.OK, MessageBoxIcon.Error);

}

}

public class WriteLog

{

public static void WriteErrLog(string str)

{

string path = Application.StartupPath + @"\ErrorLog.txt";

using (StreamWriter sw = new StreamWriter(path, true, Encoding.UTF8))

{

sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " " + str);

sw.Close();

}

}

}

}

在這個(gè)示例中,Program類是程序的入口點(diǎn)。在Main方法中,首先設(shè)置了異常處理模式,然后分別為 UI 線程和非 UI 線程的異常添加了處理程序。接著啟用可視化樣式,設(shè)置文本渲染默認(rèn)值,并運(yùn)行主窗體Form1。如果在Main方法中發(fā)生了異常,也會(huì)進(jìn)行相應(yīng)的處理,記錄日志并彈出提示框。WriteLog類負(fù)責(zé)將異常信息寫(xiě)入日志文件,日志文件名為ErrorLog.txt,保存在應(yīng)用程序的啟動(dòng)目錄下。每寫(xiě)入一條日志,都會(huì)包含當(dāng)前時(shí)間和具體的異常信息 。通過(guò)這個(gè)完整的示例,希望大家能更好地理解和掌握 Winform 全局異常捕獲處理的實(shí)現(xiàn)。

五、優(yōu)化與拓展:讓 “神器” 更強(qiáng)大

(一)異常日志記錄

在前面的代碼中,我們已經(jīng)簡(jiǎn)單實(shí)現(xiàn)了將異常信息寫(xiě)入日志文件的功能。但在實(shí)際應(yīng)用中,我們還可以對(duì)異常日志記錄進(jìn)行進(jìn)一步優(yōu)化。比如,使用專業(yè)的日志記錄框架,像 Log4net,它功能更強(qiáng)大,配置更靈活。

使用 Log4net,首先要在項(xiàng)目中添加對(duì)它的引用。然后在配置文件(如 App.config)中進(jìn)行配置,示例如下:

<configuration>

<configSections>

<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />

</configSections>

<log4net>

<appender name="FileAppender" type="log4net.Appender.FileAppender">

<file value="ErrorLog.log" />

<appendToFile value="true" />

<layout type="log4net.Layout.PatternLayout">

<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />

</layout>

</appender>

<root>

<level value="ALL" />

<appender-ref ref="FileAppender" />

</root>

</log4net>

</configuration>

在這段配置中,我們定義了一個(gè)名為FileAppender的日志輸出器,它將日志輸出到ErrorLog.log文件中。appendToFile屬性設(shè)置為true,表示每次記錄日志時(shí),會(huì)追加到文件末尾,而不是覆蓋原有內(nèi)容。layout部分定義了日志的格式,包括時(shí)間、線程、日志級(jí)別、記錄器名稱和消息內(nèi)容。

在代碼中使用 Log4net 記錄異常日志也很簡(jiǎn)單,示例如下:

using log4net;

using System.Reflection;

public class Program

{

private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

static void Main()

{

try

{

// 其他代碼

}

catch (Exception ex)

{

log.Error("發(fā)生未處理的異常", ex);

MessageBox.Show("發(fā)生致命錯(cuò)誤,請(qǐng)及時(shí)聯(lián)系作者!", "系統(tǒng)錯(cuò)誤", MessageBoxButtons.OK, MessageBoxIcon.Error);

}

}

}

在這個(gè)示例中,首先通過(guò)LogManager.GetLogger方法獲取一個(gè)日志記錄器,然后在捕獲到異常時(shí),使用log.Error方法記錄異常信息,第一個(gè)參數(shù)是自定義的錯(cuò)誤描述,第二個(gè)參數(shù)是異常對(duì)象。這樣,異常信息就會(huì)按照我們?cè)谂渲梦募卸x的格式記錄到日志文件中,方便我們后續(xù)查看和分析問(wèn)題。

(二)自定義異常處理界面

默認(rèn)的異常提示框(如MessageBox.Show彈出的框)雖然能簡(jiǎn)單地告知用戶程序出現(xiàn)了錯(cuò)誤,但不夠美觀和個(gè)性化。我們可以創(chuàng)建一個(gè)自定義的異常處理界面,讓程序在捕獲到異常時(shí),以更友好、更專業(yè)的方式向用戶展示錯(cuò)誤信息。

首先,創(chuàng)建一個(gè)新的 Winform 窗體,命名為ExceptionForm.cs。在這個(gè)窗體上,我們可以添加一些控件,如一個(gè)顯示錯(cuò)誤信息的文本框,一個(gè)用于關(guān)閉窗體的按鈕,以及一些美化界面的圖片或標(biāo)簽等。

示例代碼如下:

public partial class ExceptionForm : Form

{

public ExceptionForm(string errorMessage)

{

InitializeComponent();

txtErrorMessage.Text = errorMessage;

}

private void btnClose_Click(object sender, EventArgs e)

{

this.Close();

}

}

在這段代碼中,ExceptionForm類的構(gòu)造函數(shù)接收一個(gè)errorMessage參數(shù),用于顯示具體的異常信息。在構(gòu)造函數(shù)中,將errorMessage賦值給文本框txtErrorMessage。當(dāng)用戶點(diǎn)擊關(guān)閉按鈕btnClose時(shí),調(diào)用this.Close()方法關(guān)閉窗體。

然后,在捕獲異常的地方,修改代碼,使用自定義的異常處理界面,而不是原來(lái)的MessageBox.Show。例如,在Application_ThreadException方法和CurrentDomain_UnhandledException方法中,將MessageBox.Show替換為:

ExceptionForm exceptionForm = new ExceptionForm(str);

exceptionForm.ShowDialog();

這樣,當(dāng)程序捕獲到異常時(shí),就會(huì)彈出我們自定義的異常處理界面,向用戶展示詳細(xì)的錯(cuò)誤信息,讓用戶感受到我們對(duì)程序的用心,提升用戶對(duì)程序的好感度。

六、注意事項(xiàng):避開(kāi)異常捕獲的 “陷阱”

(一)避免過(guò)度捕獲

在設(shè)置全局異常捕獲時(shí),一定要注意避免過(guò)度捕獲異常。雖然全局異常捕獲很強(qiáng)大,但如果捕獲得太寬泛,把所有異常都一股腦兒地抓進(jìn)來(lái),可能會(huì)隱藏真正的問(wèn)題。比如說(shuō),在一個(gè)數(shù)據(jù)處理的方法中,可能會(huì)出現(xiàn)多種類型的異常,像數(shù)據(jù)格式錯(cuò)誤、數(shù)據(jù)庫(kù)連接失敗等。如果我們?cè)谌之惓2东@中沒(méi)有對(duì)這些異常進(jìn)行區(qū)分,只是簡(jiǎn)單地記錄一條 “發(fā)生異常” 的日志,那么當(dāng)程序出現(xiàn)問(wèn)題時(shí),我們很難從這條簡(jiǎn)單的日志中判斷出到底是哪里出了問(wèn)題,這會(huì)給程序的調(diào)試帶來(lái)很大的困難 。所以,在捕獲異常時(shí),要盡量做到精準(zhǔn)捕獲,針對(duì)不同類型的異常進(jìn)行不同的處理,這樣才能更好地定位和解決問(wèn)題。

(二)合理處理異常

捕獲到異常后,如何處理異常也是很關(guān)鍵的。不能簡(jiǎn)單地捕獲了異常,然后就什么都不做,或者只是簡(jiǎn)單地顯示一個(gè)錯(cuò)誤信息,這是遠(yuǎn)遠(yuǎn)不夠的。我們要根據(jù)具體的異常情況,進(jìn)行合理的處理。比如,如果是因?yàn)榫W(wǎng)絡(luò)連接問(wèn)題導(dǎo)致的異常,可以嘗試重新連接網(wǎng)絡(luò);如果是文件讀寫(xiě)錯(cuò)誤,可以提示用戶檢查文件路徑是否正確,或者嘗試創(chuàng)建一個(gè)新的文件。在處理異常時(shí),要保證程序的健壯性,不能因?yàn)橐粋€(gè)異常的出現(xiàn),就影響到整個(gè)程序的其他功能。要盡量讓程序在出現(xiàn)異常后,能夠繼續(xù)穩(wěn)定地運(yùn)行,或者至少給用戶提供一個(gè)友好的提示,讓用戶知道該如何操作,這樣才能提升程序的質(zhì)量和用戶體驗(yàn) 。

七、總結(jié)與展望:讓程序更穩(wěn)定

通過(guò)今天的分享,家人們應(yīng)該已經(jīng)深刻認(rèn)識(shí)到全局異常捕獲處理在 Winform 開(kāi)發(fā)中的重要性啦!它就像是程序的 “保護(hù)神”,能夠大大提高程序的穩(wěn)定性,讓我們的程序在面對(duì)各種異常情況時(shí),都能保持良好的運(yùn)行狀態(tài),給用戶帶來(lái)更好的體驗(yàn)。

從認(rèn)識(shí)異常這個(gè)程序中的 “小怪獸”,到學(xué)會(huì)使用全局異常捕獲給程序穿上 “防護(hù)服”,再到一步步實(shí)現(xiàn)全局異常捕獲處理的代碼,以及對(duì)它進(jìn)行優(yōu)化和拓展,我們一起走過(guò)了一段充實(shí)的學(xué)習(xí)之旅。在這個(gè)過(guò)程中,我們掌握了 UI 線程和非 UI 線程異常捕獲的方法,學(xué)會(huì)了如何處理異常信息,還了解了如何優(yōu)化異常日志記錄和創(chuàng)建自定義異常處理界面 。


閱讀原文:原文鏈接


該文章在 2025/2/5 18:35:44 編輯過(guò)
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開(kāi)發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫(kù)管理,保質(zhì)期管理,貨位管理,庫(kù)位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

黄频国产免费高清视频,久久不卡精品中文字幕一区,激情五月天AV电影在线观看,欧美国产韩国日本一区二区
精品国产福利久久久 | 永久国产盗摄一区二区 | 青草久久久国产免费观看视频 | 天堂va欧美ⅴa亚洲va在线 | 亚洲综合不卡在线视频 | 在线播放国产不卡免费视频 |