多執行緒程式設計學習筆記 使用非同步IO

2022-02-09 07:18:00 字數 4299 閱讀 4136

接上文 多執行緒程式設計學習筆記——使用併發集合(一)

接上文 多執行緒程式設計學習筆記——使用併發集合(二)

接上文 多執行緒程式設計學習筆記——使用併發集合(三)

假設以下場景,如果在客戶端執行程式,最的事情之一是有乙個響應的使用者介面。這意味著無論應用程式發生什麼,所有的使用者介面元素都要保持 快速執行,使用者能夠從應用程式得到快速響應。達到這一點並不容易!如果你嘗試在windows系統中開啟記事本並載入乙個有幾兆大小的文件,應用程式視窗將交結一段的時間,因為整個檔案要先從硬碟中載入,然後程式才能開始處理使用者輸入。

這是乙個非常重要的問題,在這種情況下,唯一方案是無論如何都要避免阻塞ui純種。這反過來意味著為了防止阻塞ui執行緒,每個與ui有關的api必須只被允許非同步呼叫 。這是windows作業系統重新公升級api的關鍵原因 ,其幾乎把每個方法替換為非同步方式。但是應用程式使用多執行緒來達到此目的會影響效能嗎?當然會。然而考慮到只有乙個使用者,那麼這是划算的。如果應用程式可以使用電腦的所有能力從而變得更加高效,而且這種能力 只為執行程式的唯一使用者服務,這是好事。

接下來看看第二種情況。如果程式執行在伺服器端,則是完全不同的情形。可伸縮性是最高優先順序,這意味著單個 使用者消耗越少的資源越好。如果為每個使用者建立多個執行緒,則可伸縮性並不好。以高效的方式來平衡應用程式資源的消耗是個非常複雜的問題。例如,在asp.net中,我們使用工作執行緒池來服務客戶端請求。這個池的工作執行緒是有限的,所以不得不最小化每個工作執行緒的使用時間以便達到高伸縮性。這意味著需要把工作執行緒越快越好地放回到池中,從而可以服務下乙個請求。如果我們啟動了乙個需要計算的非同步操作,則整個工作流程會很低效。首先從執行緒池中取出乙個工作 執行緒用以服務客戶端請求。然後取出另乙個工作執行緒並開始處理非同步操作。現在有兩個工作執行緒都在處理請求,如果第乙個執行緒能做些有用的事則非常好。可惜,通常情況下,我們簡單等待非同步 操作完成,但是我們卻消費了兩個工作 執行緒,而不是乙個。在這個場景中,非同步 比同步執行實際上更糟糕!我們不需要使用所有cpu核心,因為我們已經在服務很多客戶端,它們已經使用了cpu的所有計算能力。我們無須保持第乙個執行緒響應,因為這沒有使用者介面。那麼為什麼我們應該在服務端使用非同步呢?

答案是只有非同步輸入/輸出操作才應用使用非同步。目前,現代計算機通過有乙個磁碟驅動器來儲存檔案,一塊網絡卡來通過網路傳送與接收資料。所有這些裝置都有自己的晶元,以非常底層的方式來管理輸入/輸出操作併發訊號 給作業系統。這種執行i/o任務的方式被稱為i/o執行緒。

在asp.net中,一旦有乙個非同步的i/o操作在工作執行緒開始時,它會被立即返回到執行緒池中。當這個操作繼續執行時,這個執行緒可以服務其他的客戶端。最終,當操作發出訊號完成時,asp.net基礎設施從執行緒池中獲取乙個空閒的工作執行緒,然後會完成這個操作。

一、   非同步使用檔案

本救命學習如何使用非同步的方式讀寫乙個檔案。

1.示例**如下。

using

system;

using

system.collections.generic;

using

system.io;

using

system.linq;

using

system.text;

using

system.threading.tasks;

namespace

threadiodemo

const

int buffer_size = 4096

;

async

static

task readwriteasyncio()

",fs.isasync);

byte buffer =encoding.utf8.getbytes(createfilecontent());

var writetask = task.factory.fromasync(fs.beginwrite, fs.endwrite, buffer, 0, buffer.length, null

);

await

writetask;

}using (var fs = new filestream("

test2.txt

", filemode.create, fileaccess.readwrite, fileshare.none,

buffer_size, fileoptions.asynchronous))

",fs.isasync);

byte buffer =encoding.utf8.getbytes(createfilecontent());

var writetask = task.factory.fromasync(fs.beginwrite, fs.endwrite, buffer, 0, buffer.length, null

);

await

writetask;

}using (var fs = file.create("

test3.txt

", buffer_size, fileoptions.asynchronous))

",fs.isasync);

await

sw.writeasync(createfilecontent());}}

using (var sw = new streamwriter("

test4.txt

", true

))

",((filestream)sw.basestream).isasync);

await

sw.writeasync(createfilecontent());

}system.threading.thread.sleep(

1000

); console.writeline(

"開始非同步讀取檔案

");

task

readtasks = new task[4

];

for (int i = 0; i < 4; i++)

.txt

",i + 1

)); }

long sums = await

task.whenall(readtasks);

console.writeline(

"所有檔案中的和值:

", sums.sum());

console.writeline(

"開始刪除檔案");

task deltasks = new task[4

];

for (int i = 0; i < 4; i++)

.txt

",i + 1

); deltasks[i] =simulateasynchronousdelete(filename);

}await

task.whenall(deltasks);

console.writeline(

"刪除檔案結束");

} static

string

createfilecontent()

", new random(i).next(0, 99999

)); }

return

sb.tostring();

}async

static task sumfilecontent(string

filename)

return

sum;}}

static task simulateasynchronousdelete(string

filename)}}

2.程式執行結果,如下圖。

當程式執行時,我們以不同的方式建立了4個檔案,並寫入一些隨機資料。

在第乙個例子中,使用的是filestream類以及其方式,將非同步程式設計模式api轉換成任務。

在第二個例子中,使用的是filestream類以及其方式,不過在構造的時候提供了filestream.asynchronous引數 。

在第三個例子使用了一些簡化的api,比如file.create方法和streamwrite類。它也使用i/o執行緒,我們可以使用stream.isasync屬性來檢查。

在第四個例子說明了過分簡化 也不好。這裡我們借助非同步委託呼叫來模擬非同步i/o,其實並沒有使用非同步i/o。

然後並行地非同步地從所有檔案中讀取資料,統計每個檔案內容,然後求總和。

最後,刪除所有檔案。

python 多執行緒偽 多執行緒筆記 偽非同步IO

bio的時候,乙個客戶端對應伺服器的一條執行緒,比較耗執行緒資源.在此基礎上,對起執行緒進行優化,建立乙個執行緒池,對執行緒進行管理,可以設定乙個最大執行緒數 maxthreadcount.這樣,達到執行緒可控的目的.即使外面有遠大於執行緒數的連線過來,也不至於讓伺服器撐爆.多出的客戶端,就進入執行...

多執行緒程式設計學習筆記 非同步運算元據庫

接上文 多執行緒程式設計學習筆記 使用非同步io 接上文 多執行緒程式設計學習筆記 編寫乙個非同步的http伺服器和客戶端 三 非同步運算元據庫 本示例演示了建立資料庫,非同步運算元據,讀取資料的過程。1.程式 如下。建立資料庫文.string createcommand string.format...

多執行緒程式設計學習筆記 非同步運算元據庫

接上文 多執行緒程式設計學習筆記 使用非同步io 接上文 多執行緒程式設計學習筆記 編寫乙個非同步的http伺服器和客戶端 三 非同步運算元據庫 本示例演示了建立資料庫,非同步運算元據,讀取資料的過程。1.程式 如下。建立資料庫文.string createcommand string.format...