調用別人提供的接口無法通過try catch捕獲異常(C#),見鬼了

前幾天做CA簽名這個需求時發現一個很詭異的事情,CA簽名調用的接口是由另外一個開發部門的同事(比較難溝通的那種人)封裝并提供到我們這邊的。我們這邊只需要把數據準備好,然后調他封裝的接口即可完成簽名操作。但在測試過程中,發現他提供的接口在某些邊界條件時,會報錯。通過反編譯調試后,把報錯的堆棧及要如何修改都發給了那個同事,但是他沒鳥我,項目經理他不懂技術,也不想管這個事情(所以以后跳槽一定要跳到一個好一點的團隊)。我該做的都已經做了,沒辦法,畢竟是我負責的功能需求,到時候報錯了也是第一時間找到我。我這邊就try catch捕獲一下異常唄,神奇的事情出現了,沒捕獲到,而是被Application.ThreadException事件注冊的方法給捕獲到了(這里捕獲這個詞不算很恰當,即觸發Application.ThreadException事件對應的方法)。我們都知道,UI線程中未捕獲的異常,如果在程序的Main方法入口注冊了Application.ThreadException事件對應的方法,UI線程發生異常如果未捕獲并處理該異常就會觸發Application.ThreadException事件對應的方法。這就說明我try catch不到他那個接口的異常信息。

我這邊處理的業務邏輯代碼大概可以描述為:

通過反編譯看了一下"調用封裝CA簽名接口的代碼塊"對應的代碼,它的大概處理流程是這樣的:先通過Spring.Net接口調用CA簽名的業務邏輯,記為業務邏輯A,業務邏輯A的實現流程如下:通過反射,拿到對應的CA簽名的實現類(因為我們這邊的代碼需要兼容多個CA簽名的廠商),我們這邊對接的是網政通的CA,我這邊就只介紹一下它的大概流程:先獲取提供接口的CA用戶的用戶信息,記為步驟1;如果有用戶信息,則需要再次調用獲取用戶token信息接口,記為步驟2;獲取token用戶信息成功后,再調用獲取CA用戶二維碼信息的接口,獲取到簽章并以二維碼的形式顯示出來讓用戶進行掃碼操作,記為步驟3。如果前面的步驟1不成功,后面的步驟2,3都不用繼續操作了,直接返回CA簽名失敗,走普通簽名邏輯。同事的接口報錯就發生在步驟1中,沒有CA用戶信息時,某些代碼邏輯寫得不夠嚴謹,就報錯了。

至于我這邊為何try catch步驟1中發生的異常信息,我做了如下的猜測并進行了驗證

1? ?是不是spring.net的框架把它給處理了,結合前面使用過spring.net的經驗,排除了這種可能性

2? ?是不是被反射的方法里面報錯,調用方就抓不到異常,不太確定,那就用代碼驗證一下,后面驗證過了,反射的雖然拿不到具體的報錯堆棧信息,但還是能通過try catch捕獲到異常信息的。

3? 是不是他的代碼里面有我不知道的異常處理方式,但是看了好久,也沒看出哪里有特別的地方

4? 是不是在不同的AppDomain的異常,就捕獲不到,后面也嘗試過了,也是能捕獲的

前面的猜測無果后,就一路在網上查詢C#中try catch不到異常的情況:

網上說的情況(未驗證):有說調用非托管的代碼就捕獲不到異常

其它靠譜一點的捕獲不到異常的情況:

文章鏈接1 (未做驗證):Exception not caught using catch block

StackOverflowException:堆棧溢出異常

ThreadAbortedException:線程停止異常

OutOfMemoryException:堆棧溢出異常

ExcutionEngineException:執行引擎異常

BadImageFormatException:錯誤圖片類型異常

文章鏈接2 (未做驗證):The Uncatchable Exception

情況1:出現死遞歸導致內存異常的異常:

情況2:處理的異常中人工調用了Environment.FailFast,捕獲不到異常,程序直接退出

不過都不是我要的解決方案,當看到Environment.FailFast時,突然靈光一閃,是不是winform框架給捕獲了,然后再手工調用某個方法,會觸發Application.ThreadException事件對應的方法。有了思路后,再來反調試代碼,發現同事重寫了winfrom窗體的OnLoad方法,在重新的OnLoad方法中完成步驟1操作,而在反編譯調試中,看到winfrom窗體調用OnLoad方法的調用方捕獲了異常,并調用Application.OnException觸發Application.ThreadException事件對應的方法,如下圖:

下面我們就一起驗證一下這種情況:

測試環境:

.net framework 4.0

visual studio 2017

具體步驟如下:

1? ?新增名為TestMain的winfrom項目

2? ?編輯默認的Program類如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;namespace TestMain
{static class Program{/// <summary>/// 應用程序的主入口點。/// </summary>[STAThread]static void Main(){Application.EnableVisualStyles();Application.SetCompatibleTextRenderingDefault(false);Application.ThreadException += Application_ThreadException;Application.Run(new Form1());}private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e){MessageBox.Show("Main方法中的Application_Thread輸出,詳細錯誤信息如下:" + e.Exception.Message + e.Exception.StackTrace);}}
}

這里我注冊了Application.ThreadException事件回調的方法Application_ThreadException,如果UI線程中有沒有處理的異常,就會觸發這個方法。

3? 新增winform窗體,名為QRCodeFrm,對應的UI界面設計如下:

對應的后臺代碼如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;namespace TestMain
{public partial class QRCodeFrm : Form{public QRCodeFrm(){InitializeComponent();}protected override void OnLoad(EventArgs e){bool flag = true;if (flag){int a = 1;int b = 0;//這里會拋出異常int c = a / b;}}}
}

在這里,我們重寫了OnLoad方法,然后再進行a/b的除以0操作,這里運行時會報異常

4? ?在默認的Form1窗體中拖入一個按鈕,UI界面如下圖:

button1按鈕對應的邏輯如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using TestApi;namespace TestMain
{public partial class Form1 : Form{public Form1(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){try{QRCodeFrm frm = new QRCodeFrm();frm.ShowDialog();}catch (Exception ex){MessageBox.Show("捕獲到異常,異常信息如下:"+ex.Message+ex.StackTrace);}}}
}

在button1_Click我們進行捕獲異常

5? 生成項目并運行,結果如下:

可以看到Application.ThreadException事件回調的方法Application_ThreadException已經被調用,接著后彈出QRCodeFrm對應的窗體,如下圖:

可以看到,已經按照猜想那樣進行了輸出顯示。

回到最初的那個問題,我們要怎么處理才能捕獲到同事接口的那個異常信息呢,有個不是很靠譜的方法是,我們在合適的地方重新注冊Application.ThreadException事件方法,我們都知道,通過+=的方式注冊的Application.ThreadException事件方法,前面已經注冊過的事件方法就會被覆蓋。修改前面演示的例子中的Form1,并編輯如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using TestApi;namespace TestMain
{public partial class Form1 : Form{bool isCatch = false;string errorMessage = string.Empty;public Form1(){InitializeComponent();Application.ThreadException += New_Application_ThreadException;}private void New_Application_ThreadException(object sender, ThreadExceptionEventArgs e){errorMessage = e.Exception.Message + e.Exception.StackTrace;isCatch = true;}private void button1_Click(object sender, EventArgs e){try{QRCodeFrm frm = new QRCodeFrm();frm.ShowDialog();}catch (Exception ex){MessageBox.Show("捕獲到異常,異常信息如下:"+ex.Message+ex.StackTrace);}if (isCatch){MessageBox.Show("被捕獲的異常:"+errorMessage);}}}}

運行結果如下:

接著會彈出粗我提示框如下:

可以看到,Main方法中注冊的Application.ThreadException事件方法的已經被新注冊的方法給覆蓋了

注意:這種解決方案風險比較大,我這邊新增了一個參數進行控制是否進行Application.ThreadException事件方法的重新注冊,等同事修改了代碼,我這邊就會把參數進行關閉,這算是留了一手吧

本文的內容到此結束,內容僅代表個人觀點,如有寫得不對的地方,望指正。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/211341.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/211341.shtml
英文地址,請注明出處:http://en.pswp.cn/news/211341.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[后端卷前端2]

綁定class 為什么需要樣式綁定呢? 因為有些樣式我們希望能夠動態展示 看下面的例子: <template><div><p :class"{active:modifyFlag}">class樣式綁定</p></div> </template><script>export default {name: "goo…

人力資源服務展示網站作用有哪些

就業勞務問題往往是不少人群關注的問題&#xff0c;每個城市都聚集著大量求業者&#xff0c;而人力資源管理公司每年也會新增不少&#xff0c;對求業者來說&#xff0c;通過人力資源公司可以快速便捷的找到所需工作&#xff0c;而對公司來說&#xff0c;市場大量用戶可以帶來收…

C語言第十八集(動態內存管理)

1.malloc函數可以開辟一塊空間,具體搜: 2.malloc函數申請的空間在內存的堆區 而且它只負責幫你申請空間,不負責幫你清理空間 3.free函數可以釋放內存 4.free函數釋放的是內存中的堆區,具體搜: 5.在free函數調用完后記得把對應的指針設為空指針 6.calloc函數跟malloc函數差…

揭秘字符串的奧秘:探索String類的深層含義與源碼解讀

文章目錄 一、導論1.1 引言&#xff1a;字符串在編程中的重要性1.2 目的&#xff1a;深入了解String類的內部機制 二、String類的設計哲學2.1 設計原則&#xff1a;為什么String類如此重要&#xff1f;2.2 字符串池的概念與作用 三、String類源碼解析3.1 成員變量3.2 構造函數3…

[今來] 神話故事:金馬和碧雞

文章目錄 金馬山和碧雞山神話傳說金馬坊和碧雞坊金馬碧雞 金馬山和碧雞山 昆明山明水秀&#xff0c;北枕蛇山&#xff0c;南臨滇池&#xff0c;金馬山和碧雞山則東西夾峙&#xff0c;隔水相對&#xff0c;極盡湖光山色之美。金馬山逶迤而玲瓏&#xff0c;碧雞山峭拔而陡峻&…

[Java][Map]linkedhashmap的引入

我們可以看到&#xff1a; linkedhashmap中元素的讀取是有順序的&#xff0c;基于這種雙向鏈表 我們可以優先讀取8索引bucket上的元素 然后讀取3索引bucket上的元素&#xff0c;以及其掛載的元素 最后讀取0索引bucket上的元素 bucket是hashbucket! 這種寫法是很有序的 也是…

Pytorch初步使用

文章目錄 創建張量指定設備沿軸計算 創建張量 如果說數組是numpy的操作對象&#xff0c;那么張量Tensor就是pytorch的操作單元&#xff0c;從數據內容來說&#xff0c;與高維數組是如出一轍的&#xff0c;但作為一個類&#xff0c;其構造函數支持通過聲明張量的維度來進行初始…

clickhouse數據庫磁盤空間使用率過高問題排查

一、前言 clickhouse天天觸發磁盤使用率過高告警&#xff0c;所以需要進行排查&#xff0c;故將排查記錄一下。 二、排查過程 1、連接上進入clickhouse 2、執行語句查看各庫表使用磁盤情況 SELECT database, table, formatReadableSize(sum(bytes_on_disk)) as disk_space F…

藍橋杯物聯網競賽_STM32L071_8_ADC擴展模塊

原理圖&#xff1a; 擴展模塊原理圖&#xff1a; RP1和RP2分別對應著AIN1和AIN2&#xff0c;扭動它們&#xff0c;其對應滑動變阻器阻值也會變化 實驗板接口原理圖&#xff1a; 對應實驗板接口PB1和PB0 即AN1對應PB1, AN2對應PB0 CubMx配置&#xff1a; ADC通道IN8和IN9才對…

C#.net使用npgsql批量寫入數據入庫到postgresql數據庫

C#.net使用npgsql批量寫入數據入庫到postgresql數據庫 npgsql批量存儲數據1. 單條存儲2. 批量存儲 npgsql批量存儲數據 轉載自&#xff1a;https://blog.csdn.net/liuwanying0226/article/details/130825503 1. 單條存儲 當有類型限定時&#xff0c;例如jsonb&#xff0c;在…

uniApp項目的創建,運行到小程序

一、項目創建 1. 打開 HBuilder X 2. 右擊側邊欄點擊新建&#xff0c;選擇項目 3. 填寫項目名&#xff0c;點擊創建即可 注&#xff1a;uniapp中如果使用生命周期鉤子函數&#xff0c;建議使用哪種 ?(建議使用Vue的) 二、運行 1. 運行前先登錄 2. 登錄后點擊 manifest.js…

基于lambda簡化設計模式

前言 雖說使用設計模式可以讓復雜的業務代碼變得清晰且易于維護&#xff0c;但是某些情況下&#xff0c;開發可能會遇到我為了簡單的業務邏輯去適配設計模式的情況&#xff0c;本文筆者就以四種常見的設計模式為例&#xff0c;演示如何基于lambda來簡化設計模式的實現。 策略…

WorkPlus高效助力企業溝通的專業級即時通訊軟件

在當今高度信息化和全球化競爭的世界&#xff0c;企業需要一個高效便捷的溝通工具來促進團隊協作、提高工作效率。在這樣的背景下&#xff0c;WorkPlus作為一款專業級的即時通訊軟件應運而生。讓我們一起深入了解WorkPlus&#xff0c;探討其在企業溝通中的領先優勢和卓越能力。…

平衡二叉樹

AVL簡稱平衡二叉樹&#xff0c;縮寫為BBST&#xff0c;由蘇聯數學家 Adelse-Velskil 和 Landis 在 1962 年提出。 二叉樹是動態查找的典范&#xff0c;但在極限情況下&#xff0c;二叉樹的查找效果等同于鏈表&#xff0c;而平衡二叉樹可以完美的達到 log ? 2 n \log_2 n log2…

ElementPlus table 中嵌套 input 輸入框

文章目錄 需求分析 需求 vue3 項目中 使用UI組件庫 ElementPlus 時&#xff0c;table 中嵌入 input輸入框 分析 <template><div class"p-10"><el-table :data"tableData" border><el-table-column prop"date" label&qu…

課堂練習4.1:段式內存管理

4-1 課堂練習4.1&#xff1a;段式內存管理 段式內存管理以段為單位分配內存空間&#xff0c;段內連續&#xff0c;段間可以不連續。段可以很大&#xff0c;比如數據段、代碼段、棧段等。本實訓分析 Linux 0.11 的段式內存管理技術。 第1關1 號進程 mynext 變量的邏輯地址與線性…

cache教程 3.HTTP服務器

上一節我們實現了單機版的緩存服務&#xff0c;但是我們的目標是分布式緩存。那么&#xff0c;我們就需要把緩存服務部署到多態機器節點上&#xff0c;對外提供訪問接口。客戶端就可以通過這些接口去實現緩存的增刪改查。 分布式緩存需要實現節點間通信&#xff0c;而通信方法…

【面試經典150 | 二叉樹】翻轉二叉樹

文章目錄 寫在前面Tag題目來源題目解讀解題思路方法一&#xff1a;遞歸方法二&#xff1a;迭代 寫在最后 寫在前面 本專欄專注于分析與講解【面試經典150】算法&#xff0c;兩到三天更新一篇文章&#xff0c;歡迎催更…… 專欄內容以分析題目為主&#xff0c;并附帶一些對于本題…

4-SpringMVC

文章目錄 項目源碼地址回顧-MVC什么是MVC&#xff1f;MVC各部分組成 回顧-ServletMaven創建Web項目1、創建Maven父工程pom&#xff0c;并導入依賴2、用Maven新建一個Web Module3、代碼&#xff1a;HelloServlet.java3、代碼-hello.jsp3、代碼-web.xml4、配置Tomcat5、瀏覽器測試…

github使用方法【附安裝包】

如果你是一枚Coder&#xff0c;但是你不知道Github&#xff0c;那么我覺的你就不是一個菜鳥級別的Coder&#xff0c;因為你壓根不是真正Coder&#xff0c;你只是一個Code搬運工。說明你根本不善于突破自己&#xff01;為什么這么說原因很簡單&#xff0c;很多優秀的代碼以及各種…