4.3 多線程進階篇<中>(GCD)

来源:http://www.cnblogs.com/shorfng/archive/2016/03/26/5322525.html
-Advertisement-
Play Games

<!--?xml version="1.0" encoding="UTF-8" standalone="no"?--> 更正:隊列名稱的作用的圖中,箭頭標註的有些問題,已修正 1.0 GCD簡介 GCD概念 :(Grand Central Dispatch)可譯為“偉大的中樞調度器” 純C語言,提供 ...


更正:隊列名稱的作用的圖中,箭頭標註的有些問題,已修正     1.0 GCD簡介   GCD概念 :(Grand Central Dispatch)可譯為“偉大的中樞調度器”
  • 純C語言,提供了非常多強大的函數

GCD 的優勢:
 
  • GCD是蘋果公司為多核的並行運算提出的解決方案
  • GCD會自動利用更多的CPU內核(比如雙核、四核)
  • GCD會自動管理線程的生命周期(創建線程、調度任務、銷毀線程)
  • 程式員只需要告訴GCD想要執行什麼任務,不需要編寫任何線程管理代碼

GCD的兩個核心概念:
  1) 任務:執行什麼操作 2) 隊列:用來存放任務   註意: (1)GCD存在於 libdispatch 這個庫中,這個調度庫包含了GCD的所有的東西,但任何IOS程式,預設就載入了這個庫,在程式運行的過程中會動態的載入這個庫,不需要我們手動導入。 (2)GCD是純C語言的,因此我們在編寫GCD相關代碼的時候,面對的函數,而不是方法。 (3)GCD中的函數大多數都以dispatch開頭。   2.0 GCD的使用 GCD的使用步驟: 步驟1 : 創建隊列 步驟2 : 創建任務
  • 確定想做的事情
步驟3:把任務添加到隊列
  • GCD會自動將隊列中的任務取出,放到對應的線程中執行
  • 任務的取出遵循隊列的FIFO原則:先進先出,後進後出
  2.1 GCD的使用 - 任務 任務的執行: 有兩個函數來執行任務:
  • 同步
  • 非同步
說明:把右邊的參數(任務)dispatch_block_t block 提交給左邊的參數(隊列)dispatch_queue_t queue 進行執行。
 11)任務的執行:同步
 2 
 3 //queue:隊列    block:任務
 4 dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
 5 
 62)任務的執行:非同步
 7 
 8 - 函數1
 9 
10 //queue:隊列    block:任務
11 dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
12 
13 - 函數2
14 
15 // 在前面的任務執行結束後它才執行,而且它後面的任務等它執行完成之後才會執行
16 dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);

  【區別】同步 & 非同步:同步和非同步決定了要不要開啟新的線程
  • 同步:只能在當前線程中執行任務,不具備開啟新線程的能力
  • 非同步:可以在新的線程中執行任務,具備開啟新線程的能力 
【區別】併發 & 串列:併發和串列決定了任務的執行方式
  • 併發:允許多個任務併發(同時)執行
  • 串列:一個任務執行完畢後,再執行下一個任務

   2.2 GCD的使用 - 隊列 隊列分類: (1)併發隊列(Concurrent Dispatch Queue)
  • 可以讓多個任務併發(同時)執行(自動開啟多個線程同時執行任務)
  • 併發功能只有在非同步(dispatch_async)函數下才有效
(2)串列隊列(Serial Dispatch Queue)
  • 讓任務一個接著一個地執行(一個任務執行完畢後,再執行下一個任務)
  release:
  • 凡是函數名種帶有create\copy\new\retain等字眼, 都應該在不需要使用這個數據的時候進行release
  • GCD的數據類型在ARC環境下不需要再做release         dispatch_release(queue); // 非ARC需要釋放手動創建的隊列
  • CF(Core Foundation)的數據類型在ARC環境下還是需要再做release
  隊列名稱的作用:將來調試的時候,可以看得出任務是在哪個隊列中執行的。   2.2.1 創建隊列 - 併發隊列 並行隊列中的任務是多個任務同時執行的  :
(1)如果非同步任務前面有同步任務 就會先執行同步任務同步任務是按順序執行的任務等他執行完了才會執行並行中的非同步任務  (可以做到阻塞 控制任務的執行順序)
(2)如果非同步任務後面有同步任務  兩個任務會並行(同時)執行
 
 1 方式1 - 手動創建併發隊列:
 2 
 3 dispatch_queue_create(
 4     constchar *label,           // 隊列名稱
 5     dispatch_queue_attr_t attr  // 隊列的類型
 6 );
 7 
 8 // 1.創建併發隊列   DISPATCH_QUEUE_CONCURRENT (併發)
 9 dispatch_queue_t queue = dispatch_queue_create(“TD", DISPATCH_QUEUE_CONCURRENT);
10 
11 // 2.非ARC需要釋放手動創建的隊列
12 dispatch_release(queue);
13 
14 方式2 - 獲取全局併發隊列:(GCD預設已經提供了全局的併發隊列,供整個應用使用,可以無需手動創建)
15 
16 Xcode 7.2定義方式:
17 dispatch_get_global_queue(
18        long identifier,    // 隊列的優先順序
19        unsignedlong flags  // 此參數暫時無用,用0即可
20 );
21 
22 全局併發隊列的優先順序:(級別由高到低)
23 
24 #define DISPATCH_QUEUE_PRIORITY_HIGH 2               //
25 #define DISPATCH_QUEUE_PRIORITY_DEFAULT 0            // 預設(中)
26 #define DISPATCH_QUEUE_PRIORITY_LOW (-2)             //
27 #define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 後臺
28 
29 // 獲取全局併發隊列
30 dispatch_queue_t queue =
31       dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

 

2.2.1【代碼】同步 + 併發 在實際開發中,同步任務可以保證執行完成之後,才讓後續的非同步任務開始執行,用於控制任務之間的先後順序,在後臺線程中,處理“用戶登錄”
 1 #import "ViewController.h"
 2 
 3 @interface ViewController ()
 4 
 5 @end
 6 
 7 @implementation ViewController
 8 
 9 - (void)viewDidLoad {
10   [super viewDidLoad];
11   // Do any additional setup after loading the view, typically from a nib.
12 }
13 
14 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
15   [self syncConcurrent];
16 }
17 
18 #pragma mark - 同步函數 + 併發隊列:不會開啟新的線程,在當前線程執行任務(主線程),順序執行,併發隊列失去了併發的功能
19 - (void)syncConcurrent {
20   NSLog(@"同步併發 ----- begin");
21 
22   // 1.獲得全局的併發隊列
23   dispatch_queue_t queue =
24       dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
25 
26   // 2.將任務加入隊列
27   dispatch_sync(queue, ^{
28     NSLog(@"1-----%@", [NSThread currentThread]);
29   });
30   dispatch_sync(queue, ^{
31     NSLog(@"2-----%@", [NSThread currentThread]);
32   });
33   dispatch_sync(queue, ^{
34     NSLog(@"3-----%@", [NSThread currentThread]);
35   });
36 
37   NSLog(@"同步併發 ----- end");
38 }
39 
40 #pragma mark - 寫法2
41 - (void)concurrentSync {
42   // 1. 創建併發隊列
43   dispatch_queue_t conCurrentQueue =
44       dispatch_queue_create("TD", DISPATCH_QUEUE_CONCURRENT);
45 
46   // 2. 創建任務
47   void (^task1)() = ^() {
48     NSLog(@"---task1---%@", [NSThread currentThread]);
49   };
50 
51   void (^task2)() = ^() {
52     NSLog(@"---task2---%@", [NSThread currentThread]);
53   };
54 
55   void (^task3)() = ^() {
56     NSLog(@"---task3---%@", [NSThread currentThread]);
57   };
58 
59   // 3. 將同步任務添加到併發隊列中
60   dispatch_sync(conCurrentQueue, task1);
61   dispatch_sync(conCurrentQueue, task2);
62   dispatch_sync(conCurrentQueue, task3);
63 }
64 
65 - (void)didReceiveMemoryWarning {
66   [super didReceiveMemoryWarning];
67   // Dispose of any resources that can be recreated.
68 }
69 
70 @end
71 
72 列印結果:
73 
74 2016-03-20 00:04:08.387 同步併發[1702:246074] 同步併發 ----- begin
75 2016-03-20 00:04:08.387 同步併發[1702:246074] 1-----<NSThread: 0x7fe963d07360>{number = 1, name = main}
76 2016-03-20 00:04:08.387 同步併發[1702:246074] 2-----<NSThread: 0x7fe963d07360>{number = 1, name = main}
77 2016-03-20 00:04:08.388 同步併發[1702:246074] 3-----<NSThread: 0x7fe963d07360>{number = 1, name = main}
78 2016-03-20 00:04:08.388 同步併發[1702:246074] 同步併發 ----- end
79 
80 2016-03-20 00:05:07.968 同步併發[1724:247291] ---task1---<NSThread: 0x7f8e71400d20>{number = 1, name = main}
81 2016-03-20 00:05:07.969 同步併發[1724:247291] ---task2---<NSThread: 0x7f8e71400d20>{number = 1, name = main}
82 2016-03-20 00:05:07.969 同步併發[1724:247291] ---task3---<NSThread: 0x7f8e71400d20>{number = 1, name = main}
View Code

 

2.2.1【代碼】非同步 + 併發
 1 #import "ViewController.h"
 2 
 3 @interface ViewController ()
 4 
 5 @end
 6 
 7 @implementation ViewController
 8 
 9 - (void)viewDidLoad {
10   [super viewDidLoad];
11   // Do any additional setup after loading the view, typically from a nib.
12 }
13 
14 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
15   [self asyncConcurrent];
16 }
17 
18 #pragma mark - 非同步函數 + 併發隊列:可以同時開啟多條線程,在當前線程執行任務(主線程),無序執行(按照任務添加到隊列中的順序被調度),線程條數具體由`可調度線程池/底層線程池`來決定
19 - (void)asyncConcurrent {
20   NSLog(@"非同步併發 ----- begin");
21 
22   // 1.獲得全局的併發隊列
23   dispatch_queue_t queue =
24       dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
25 
26   // 2.將任務加入隊列
27   dispatch_sync(queue, ^{
28     NSLog(@"1-----%@", [NSThread currentThread]);
29   });
30   dispatch_sync(queue, ^{
31     NSLog(@"2-----%@", [NSThread currentThread]);
32   });
33   dispatch_sync(queue, ^{
34     NSLog(@"3-----%@", [NSThread currentThread]);
35   });
36 
37   NSLog(@"非同步併發 ----- begin");
38 }
39 
40 #pragma mark - 寫法2
41 - (void)concurrentAsync {
42   // 1.創建併發隊列
43   dispatch_queue_t conCurrentQueue =
44       dispatch_queue_create("TD", DISPATCH_QUEUE_CONCURRENT);
45 
46   // 2. 創建任務
47   void (^task1)() = ^() {
48     NSLog(@"---task1---%@", [NSThread currentThread]);
49   };
50 
51   void (^task2)() = ^() {
52     NSLog(@"---task2---%@", [NSThread currentThread]);
53   };
54 
55   void (^task3)() = ^() {
56     NSLog(@"---task3---%@", [NSThread currentThread]);
57   };
58 
59   // 3. 將非同步任務添加到併發隊列中
60   dispatch_async(conCurrentQueue, task1);
61   dispatch_async(conCurrentQueue, task2);
62   dispatch_async(conCurrentQueue, task3);
63 }
64 
65 - (void)didReceiveMemoryWarning {
66   [super didReceiveMemoryWarning];
67   // Dispose of any resources that can be recreated.
68 }
69 
70 @end
71 
72 列印結果:
73 
74 2016-03-20 00:11:16.307 非同步併發[1879:254274] 非同步併發 ----- begin
75 2016-03-20 00:11:16.308 非同步併發[1879:254274] 1-----<NSThread: 0x7fd598d02490>{number = 1, name = main}
76 2016-03-20 00:11:16.308 非同步併發[1879:254274] 2-----<NSThread: 0x7fd598d02490>{number = 1, name = main}
77 2016-03-20 00:11:16.308 非同步併發[1879:254274] 3-----<NSThread: 0x7fd598d02490>{number = 1, name = main}
78 2016-03-20 00:11:16.308 非同步併發[1879:254274] 非同步併發 ----- begin
79 
80 2016-03-20 00:18:18.557 非同步併發[1945:260502] ---task2---<NSThread: 0x7fbf68d927b0>{number = 3, name = (null)}
81 2016-03-20 00:18:18.557 非同步併發[1945:260628] ---task3---<NSThread: 0x7fbf68e24570>{number = 4, name = (null)}
82 2016-03-20 00:18:18.557 非同步併發[1945:260503] ---task1---<NSThread: 0x7fbf68f15ae0>{number = 2, name = (null)}
View Code

 

2.2.2 創建隊列 - 串列隊列

 1 手動創建串列隊列:
 2 
 3 dispatch_queue_create(
 4     constchar *label,           // 隊列名稱
 5     dispatch_queue_attr_t attr  // 隊列的類型
 6 );
 7 
 8 //1.創建串列隊列
 9 
10 //方式1:DISPATCH_QUEUE_SERIAL (串列)
11 dispatch_queue_t queue = dispatch_queue_create(“TD", DISPATCH_QUEUE_SERIAL);
12 //方式2:傳 NULL
13 dispatch_queue_t queue = dispatch_queue_create(“TD", NULL);
14 
15 // 2.非ARC需要釋放手動創建的隊列
16 dispatch_release(queue);

  • 串列隊列中的任務都是按順序執行,誰在前就先執行誰
  • 主線程和子線程平等,一樣誰在前選執行誰
  • 執行完一個才會執行下一個任務
   2.2.2【代碼】同步 + 串列
  • 串列隊列中的任務都是按順序執行,誰在前就先執行誰
  • 主線程和子線程平等,一樣誰在前選執行誰
  • 執行完一個才會執行下一個任務
 1 #import "ViewController.h"
 2 
 3 @interface ViewController ()
 4 
 5 @end
 6 
 7 @implementation ViewController
 8 
 9 - (void)viewDidLoad {
10   [super viewDidLoad];
11   // Do any additional setup after loading the view, typically from a nib.
12 }
13 
14 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
15   [self syncSerial];
16 }
17 
18 #pragma mark - 同步函數 + 串列隊列:不會開啟新的線程,在當前線程執行任務(主線程),任務是串列的(順序執行)
19 - (void)syncSerial {
20   NSLog(@"同步串列 ----- begin");
21 
22   // 1.創建串列隊列
23   dispatch_queue_t queue = dispatch_queue_create("TD", DISPATCH_QUEUE_SERIAL);
24 
25   // 2.將任務加入隊列
26   dispatch_sync(queue, ^{
27     NSLog(@"1-----%@", [NSThread currentThread]);
28   });
29   dispatch_sync(queue, ^{
30     NSLog(@"2-----%@", [NSThread currentThread]);
31   });
32   dispatch_sync(queue, ^{
33     NSLog(@"3-----%@", [NSThread currentThread]);
34   });
35 
36   NSLog(@"同步串列 ----- end");
37 }
38 
39 #pragma mark - 寫法2
40 - (void)serialSyncDemo {
41   // 1.創建隊列
42   dispatch_queue_t serialQueue =
43       dispatch_queue_create("TD", DISPATCH_QUEUE_SERIAL);
44 
45   // 2.創建任務
46   void (^task1)() = ^() {
47     NSLog(@"task1---%@", [NSThread currentThread]);
48   };
49 
50   void (^task2)() = ^() {
51     NSLog(@"task2---%@", [NSThread currentThread]);
52   };
53 
54   void (^task3)() = ^() {
55     NSLog(@"task3---%@", [NSThread currentThread]);
56   };
57 
58   // 3.將同步任務,添加到串列隊列
59   dispatch_sync(serialQueue, task3);
60   dispatch_sync(serialQueue, task1);
61   dispatch_sync(serialQueue, task2);
62 }
63 
64 - (void)didReceiveMemoryWarning {
65   [super didReceiveMemoryWarning];
66   // Dispose of any resources that can be recreated.
67 }
68 
69 @end
70 
71 列印結果:
72 
73 2016-03-20 00:38:13.648 同步串列[2145:276628] 同步串列 ----- begin
74 2016-03-20 00:38:13.649 同步串列[2145:276628] 1-----<NSThread: 0x7fab52f04910>{number = 1, name = main}
75 2016-03-20 00:38:13.649 同步串列[2145:276628] 2-----<NSThread: 0x7fab52f04910>{number = 1, name = main}
76 2016-03-20 00:38:13.649 同步串列[2145:276628] 3-----<NSThread: 0x7fab52f04910>{number = 1, name = main}
77 2016-03-20 00:38:13.649 同步串列[2145:276628] 同步串列 ----- end
78 
79 2016-03-20 00:47:53.272 同步串列[2248:284920] task1---<NSThread: 0x7fd910c05150>{number = 1, name = main}
80 2016-03-20 00:47:53.273 同步串列[2248:284920] task2---<NSThread: 0x7fd910c05150>{number = 1, name = main}
81 2016-03-20 00:47:53.273 同步串列[2248:284920] task3---<NSThread: 0x7fd910c05150>{number = 1, name = main}
View Code

 

2.2.2【代碼】非同步 + 串列
  • 串列隊列中的任務都是按順序執行,誰在前就先執行誰
  • 主線程和子線程平等,一樣誰在前選執行誰
  • 執行完一個才會執行下一個任務
串列隊列,非同步任務,在多線程中,是斯坦福大學最推薦的一種多線程方式!
  • 優點:將任務放在其他線程中工作,每個任務順序執行,便於調試
  • 缺點:併發能力不強,最多只能使用一條線程!
 
 1 #import "ViewController.h"
 2 
 3 @interface ViewController ()
 4 
 5 @end
 6 
 7 @implementation ViewController
 8 
 9 - (void)viewDidLoad {
10   [super viewDidLoad];
11   // Do any additional setup after loading the view, typically from a nib.
12 }
13 
14 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
15   [self asyncSerial];
16 }
17 
18 #pragma mark - 非同步函數 + 串列隊列:會開啟新的線程,在子線程執行任務,任務是串列的(順序執行),只開一條線程
19 - (void)asyncSerial {
20   NSLog(@"非同步串列 ----- begin");
21   NSLog(@"主線程  ----- %@", [NSThread mainThread]);
22 
23   // 1.創建串列隊列
24   //寫法1:
25   dispatch_queue_t queue = dispatch_queue_create("TD", DISPATCH_QUEUE_SERIAL);
26   //寫法2:
27   dispatch_queue_t queue = dispatch_queue_create("TD", NULL);
28 
29   // 2.將任務加入隊列
30   dispatch_async(queue, ^{
31     NSLog(@"1-----%@", [NSThread currentThread]);
32   });
33   dispatch_async(queue, ^{
34     NSLog(@"2-----%@", [NSThread currentThread]);
35   });
36   dispatch_async(queue, ^{
37     NSLog(@"3-----%@", [NSThread currentThread]);
38   });
39 
40   NSLog(@"非同步串列 ----- end");
41 }
42 
43 #pragma mark - 寫法2
44 - (void)serialAsyncDemo {
45   // 1.創建隊列
46   dispatch_queue_t serialQueue =
47       dispatch_queue_create("TD", DISPATCH_QUEUE_SERIAL);
48 
49   // 2.創建任務
50   void (^task1)() = ^() {
51     NSLog(@"task1---%@", [NSThread currentThread]);
52   };
53 
54   void (^task2)() = ^() {
55     NSLog(@"task2---%@", [NSThread currentThread]);
56   };
57 
58   void (^task3)() = ^() {
59     NSLog(@"task3---%@", [NSThread currentThread]);
60   };
61 
62   // 3.將非同步任務添加到串列隊列<

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 廣播的概念 現實中:我們常常使用電臺通過發送廣播發佈消息,買個收音機,就能收聽 Android:系統在產生某個事件時發送廣播,應用程式使用廣播接收者接收這個廣播,就知道系統產生了什麼事件。Android系統在運行的過程中,會產生很多事件,比如開機、電量改變、收發簡訊、撥打電話、屏幕解鎖 廣播接收者的 ...
  • 本篇主要講述在 OC 開發中主要涉及到的運行時機制: 運行時的工作: 運行時在 OC 中的工作:OC 語言的設計模式決定了儘可能的把程式從編譯和鏈接時推遲到運行時。只要有可能,OC 總是使用動態的方式來解決問題。這意味著 OC 語言不僅需要一個編譯器,同時也需要一個運行時系統來執行編譯好的代碼。這兒 ...
  • Atitit.反編譯apk android源碼以及防止反編譯apk 1.1. Tool apk逆向助手1 1.2. 二、使用dex2jar + jd-gui 得到apk的java源碼1 1.3. 用命令(dex2jar.bat classes.dex)得到一個 jar文件1 2. Apk文件的結構2 ...
  • 一個但凡涉及到用戶信息的應用,總少不了設置用戶圖像這個小功能。之前做這塊的時候只是簡單的複製粘貼導致最近再做這個功能的時候,卻發現問題很多,拍照及相冊選擇後啟動系統裁剪要不崩潰要不就是沒有返回數據,今天好好梳理一下這個功能。 調用系統拍照界面: 調用系統相冊界面: 這裡補充一下,很多網友都說andr ...
  • 在AndroidManifest.xml文件中有<application android:theme="@style/AppTheme">,其中的@style/AppTheme是引用的res/values/styles.xml 中的主題樣式,也有可能是引用的 res/values-v11/style ...
  • 因重新升級了系統,一步步搭建react-native環境。 1、安裝Homebrew 打開終端命令->ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" (註:ruby命令 ...
  • 本人博客園首頁 http://home.cnblogs.com/u/liuenwen/ 這兒收集一些實在常用的網站,希望各位看到的朋友,如果有好的網站,希望您分享在評價里,大家一起學習!!! github的官網: https://github.com/ github裡面一些常用第三方的集合 http ...
  • TabBarController 是在 ios 開發過程中使用較為頻繁的一個 Controller,但是在使用過程中經常會遇到一些問題,例如本文所要解決的,如何修改 TabBar 選中時文字及圖片的顏色。 如果需要,可以從這裡下載完整的代碼。 首先,我們創建一個新的項目,使用 TabBarContr ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...