場(chǎng)景
Winform中怎樣使用HttpClient調(diào)用http的get和post接口并將接口返回json數(shù)據(jù)解析為實(shí)體類:
Winform中怎樣使用HttpClient調(diào)用http的get和post接口并將接口返回json數(shù)據(jù)解析為實(shí)體類_winform請(qǐng)求http接口_霸道流氓氣質(zhì)的博客-CSDN博客
參考前面使用HttpClient調(diào)用http的get和post接口的小示例,
需要定位調(diào)用http的get接口并對(duì)接口返回?cái)?shù)據(jù)進(jìn)行后續(xù)處理。
關(guān)于定時(shí)器的使用在下面文章中有涉及到
Winform中使用mysqldump實(shí)現(xiàn)選擇部分表定期備份mysql數(shù)據(jù)庫(kù):
Winform中使用mysqldump實(shí)現(xiàn)選擇部分表定期備份mysql數(shù)據(jù)庫(kù)_mysqldump 部分表_霸道流氓氣質(zhì)的博客-CSDN博客
注:
博客:
霸道流氓氣質(zhì)的博客_CSDN博客-C#,架構(gòu)之路,SpringBoot領(lǐng)域博主
實(shí)現(xiàn)
1、初次業(yè)務(wù)實(shí)現(xiàn)邏輯比較簡(jiǎn)單,未考慮任務(wù)同步執(zhí)行堵塞UI線程的情況。
在測(cè)試時(shí)發(fā)現(xiàn),當(dāng)http接口不通時(shí),而又未設(shè)置httpClient的最大超時(shí)響應(yīng)時(shí)間,
會(huì)導(dǎo)致頁(yè)面卡死無(wú)響應(yīng)。
優(yōu)化前的代碼:
??????? private void convertPositionControl() {
??????????? try
??????????? {
??????????????? //獲取接口數(shù)據(jù)
??????????????? var positionData = requestGetHttpData(positionCalculateUrl);
??????????????? //http請(qǐng)求不到數(shù)據(jù),啥也不干
??????????????? if (null == positionData)
??????????????? {
??????????????????? return;
??????????????? }//請(qǐng)求到數(shù)據(jù),則進(jìn)行數(shù)據(jù)處理
??????????????? else
??????????????? {
?
??????????????? }
??????????? }
??????????? catch (Exception exception)
??????????? {
??????????????? textBox_log.AppendText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":獲取接口出錯(cuò):");
??????????????? textBox_log.AppendText("\r\n");
??????????????? textBox_log.AppendText(exception.Message);
??????????? }
??????? }
上面是在定時(shí)器中具體執(zhí)行的代碼,省略部分邏輯,其中請(qǐng)求http接口的方法是
requestGetHttpData,參數(shù)getAllBaseStationInfoUrl是接口url。
然后請(qǐng)求接口的方法具體實(shí)現(xiàn)是
??????? private string requestGetHttpData(string apiUrl)
??????? {
??????????? try {
??????????????? //調(diào)用接口請(qǐng)求數(shù)據(jù)
??????????????? var originAddressUrl = apiUrl;
??????????????? //請(qǐng)求接口數(shù)據(jù)
??????????????? if (null == httpClient) {
??????????????????? httpClient = new HttpClient();
??????????????? }
??????????????? var url = new Uri(originAddressUrl);
??????????????? var response = httpClient.GetAsync(url).Result;
??????????????? var data = response.Content.ReadAsStringAsync().Result;
??????????????? return data;
??????????? }
??????????? catch (Exception exception) {???
??????????????? textBox_log.AppendText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":調(diào)用接口" + apiUrl + "異常:" + exception.Message);
??????????????? textBox_log.AppendText("\r\n");
??????????????? return null;
??????????? }
??????? }
這里直接未作任何考慮,只是考慮接口正常的情況。
但是當(dāng)接口不存在或者報(bào)錯(cuò)時(shí)就會(huì)導(dǎo)致頁(yè)面卡死。
注意:
HttpClient的預(yù)熱機(jī)制,不要在每次請(qǐng)求接口時(shí)都要初始化
httpClient = new HttpClient();
這里放在頁(yè)面加載完成之后進(jìn)行初始化一次
??????? private void Form1_Load(object sender, EventArgs e)
??????? {
??????????? httpClient = new HttpClient();
??????????? httpClient.Timeout = TimeSpan.FromSeconds(httpClientMaxResponseSeconds);
??????? }
另外需要給httpClient設(shè)置最大響應(yīng)超時(shí)時(shí)長(zhǎng)
2、C# 中 HttpClient設(shè)置最大響應(yīng)超時(shí)時(shí)長(zhǎng)
?httpClient.Timeout = TimeSpan.FromSeconds(httpClientMaxResponseSeconds);
這里httpClientMaxResponseSeconds是
private double httpClientMaxResponseSeconds = 2;
這里設(shè)置為2秒。
后續(xù)建議將其優(yōu)化為單例模式或其他更好的模式。
3、上面卡住問題是因?yàn)樵谕綀?zhí)行的方法中,請(qǐng)求接口的方法會(huì)堵塞UI線程/主線程。
需要將上面請(qǐng)求接口的方法修改成異步任務(wù)執(zhí)行的機(jī)制,避免影響UI線程。
這塊在之前寫mqtt連接時(shí)用到到,但是當(dāng)時(shí)不知其所以然。
?
Winform中使用MQTTnet實(shí)現(xiàn)MQTT的服務(wù)端和客戶端之間的通信以及將訂閱的消息保存到文件:
Winform中使用MQTTnet實(shí)現(xiàn)MQTT的服務(wù)端和客戶端之間的通信以及將訂閱的消息保存到文件_mqtt winform_霸道流氓氣質(zhì)的博客-CSDN博客
4、異步
同步和異步主要用于修飾方法。當(dāng)一個(gè)方法被調(diào)用時(shí),調(diào)用者需要等待該方法執(zhí)行完畢并返回才能繼續(xù)執(zhí)行,
我們稱這個(gè)方法是同步方法;當(dāng)一個(gè)方法被調(diào)用時(shí)立即返回,并獲取一個(gè)線程執(zhí)行該方法內(nèi)部的業(yè)務(wù),
調(diào)用者不用等待該方法執(zhí)行完畢,我們稱這個(gè)方法為異步方法。
異步的好處在于非阻塞(調(diào)用線程不會(huì)暫停執(zhí)行去等待子線程完成),因此我們把一些不需要立即使用結(jié)果、
較耗時(shí)的任務(wù)設(shè)為異步執(zhí)行,可以提高程序的運(yùn)行效率。net4.0在ThreadPool的基礎(chǔ)上推出了Task類,
微軟極力推薦使用Task來執(zhí)行異步任務(wù),現(xiàn)在C#類庫(kù)中的異步方法基本都用到了Task;net5.0推出了async/await,
讓異步編程更為方便。
在C#5.0中出現(xiàn)的 async和await ,讓異步編程變得更簡(jiǎn)單。
關(guān)于async Task 和await的使用不再詳述,具體可自行學(xué)習(xí)。
下面參考一個(gè)網(wǎng)絡(luò)上的示例
class Program
??? {
??????? static void Main(string[] args)
??????? {
??????????? string content = GetContentAsync(Environment.CurrentDirectory + @"/test.txt").Result;
??????????? //調(diào)用同步方法
??????????? //string content = GetContent(Environment.CurrentDirectory + @"/test.txt");
??????????? Console.WriteLine(content);
??????????? Console.ReadKey();
??????? }
??????? //異步讀取文件內(nèi)容
??????? async static Task<string> GetContentAsync(string filename)
??????? {
???????????
??????????? FileStream fs = new FileStream(filename, FileMode.Open);
??????????? var bytes = new byte[fs.Length];
??????????? //ReadAync方法異步讀取內(nèi)容,不阻塞線程
??????????? Console.WriteLine("開始讀取文件");
??????????? int len = await fs.ReadAsync(bytes, 0, bytes.Length);
??????????? string result = Encoding.UTF8.GetString(bytes);
??????????? return result;
??????? }
??????? //同步讀取文件內(nèi)容
??????? static string GetContent(string filename)
??????? {
??????????? FileStream fs = new FileStream(filename, FileMode.Open);
??????????? var bytes = new byte[fs.Length];
??????????? //Read方法同步讀取內(nèi)容,阻塞線程
??????????? int len =? fs.Read(bytes, 0, bytes.Length);
??????????? string result = Encoding.UTF8.GetString(bytes);
??????????? return result;
??????? }
??? }
優(yōu)化代碼
首先將HttpClient修改為單例模式,避免每次請(qǐng)求接口都去new
新建類
{
??? class Global
??? {
??????? private static string _lockFlag = "GlobalLock";
??????? private static Global _instance;
??????? //http請(qǐng)求客戶端
??????? public HttpClient httpClient = new HttpClient();
??????? private Global()
??????? {
??????? }
??????? public static Global Instance
??????? {
??????????? get
??????????? {
??????????????? lock (_lockFlag)
??????????????? {
??????????????????? if (_instance == null)
??????????????????? {
??????????????????????? _instance = new Global();
??????????????????? }
??????????????????? return _instance;
??????????????? }
??????????? }
??????? }
??? }
}
關(guān)于全局/單例的實(shí)現(xiàn)可以參考如下:
C#中全局作用域的常量、字段、屬性、方法的定義與使用:
C#中全局作用域的常量、字段、屬性、方法的定義與使用_霸道流氓氣質(zhì)的博客-CSDN博客
這里就一個(gè)窗體,所以在窗體初始化后設(shè)置其響應(yīng)時(shí)長(zhǎng),也可放在全局工具類的get方法中
??????? private void Form1_Load(object sender, EventArgs e)
??????? {
??????????? //設(shè)置http連接超時(shí)時(shí)間
??????????? Global.Instance.httpClient.Timeout = TimeSpan.FromSeconds(httpClientMaxResponseSeconds);
??????? }
然后改造請(qǐng)求Http接口的方法
??????? private async Task<string> requestGetHttpData(string apiUrl)
??????? {
??????????? try {
??????????????? var originAddressUrl = apiUrl;
??????????????? //請(qǐng)求接口數(shù)據(jù)????????
??????????????? var url = new Uri(originAddressUrl);
??????????????? string jsonResponse = await Global.Instance.httpClient.GetStringAsync(url);
??????????????? return jsonResponse;
??????????? }
??????????? catch (Exception exception) {
??????????????? textBox_log.AppendText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":調(diào)用接口" + apiUrl + "異常:" + exception.Message);
??????????????? textBox_log.AppendText("\r\n");
????????????????
??????????????? return null;
??????????? }
??????? }
將方法添加async Task<string>,注意這里httpClient調(diào)用GetStringAsync方法前面加了await
然后定時(shí)器執(zhí)行中的方法調(diào)用修改為文章來源:http://www.zghlxwxcb.cn/news/detail-788492.html
??????? private async Task convertPositionControl() {
??????????? try
??????????? {
??????????????? //獲取接口數(shù)據(jù)
??????????????? var positionData = await requestGetHttpData(positionCalculateUrl);
??????????????? //http請(qǐng)求不到數(shù)據(jù),啥也不干
??????????????? if (null == positionData)
??????????????? {
??????????????????? return;
??????????????? }//請(qǐng)求到數(shù)據(jù),則進(jìn)行數(shù)據(jù)處理
??????????????? else
??????????????? {
???????????????????
??????????????? }
??????????? }
??????????? catch (Exception exception)
??????????? {
??????????????? textBox_log.AppendText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":獲取接口出錯(cuò):");
??????????????? textBox_log.AppendText("\r\n");
??????????????? textBox_log.AppendText(exception.Message);
??????????? }
??????? }
至此,不會(huì)導(dǎo)致界面卡住的現(xiàn)象。文章來源地址http://www.zghlxwxcb.cn/news/detail-788492.html
到了這里,關(guān)于Winform中使用HttpClient(設(shè)置最大超時(shí)響應(yīng)時(shí)間)調(diào)用接口并做業(yè)務(wù)處理時(shí)界面卡住,使用async Task await異步任務(wù)編程優(yōu)化的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!