同步和重迭的管道 I/O

ReadFileWriteFileTransactNamedPipeConnectNamedPipe函式可以在管道上同步或非同步執行輸入和輸出作業。 當函式以同步方式執行時,它不會傳回,直到執行中的作業完成為止。 這表示呼叫執行緒的執行可能會無限期地遭到封鎖,同時等候耗時的作業完成。 當函式以非同步方式執行時,它會立即傳回,即使作業尚未完成也一樣。 這可讓在背景執行耗時的作業,同時呼叫執行緒可以自由執行其他工作。

使用非同步 I/O 可讓管道伺服器使用執行下列步驟的迴圈:

  1. 在呼叫 wait 函式中指定多個事件物件,並等候其中一個物件設定為已發出訊號的狀態。
  2. 使用 wait 函式的傳回值來判斷哪些重迭作業已完成。
  3. 執行清除已完成作業所需的工作,並起始該管道控制碼的下一個作業。 這可能會牽涉到為相同的管道控點啟動另一個重迭的作業。

重迭的作業可讓一個管道同時讀取和寫入資料,以及讓單一線程在多個管道控點上執行同時 I/O 作業。 這可讓單一執行緒管道伺服器有效率地處理與多個管道用戶端的通訊。 如需範例,請參閱 使用重迭 I/O 的具名管道伺服器

若要讓管道伺服器使用同步作業與多個用戶端通訊,它必須為每個管道用戶端建立個別的執行緒,以便在其他執行緒正在等候時執行一或多個執行緒。 如需使用同步作業的多執行緒管道伺服器的範例,請參閱 多執行緒管道伺服器

啟用非同步作業

只有在您為指定的管道控制碼啟用重迭模式並指定迭的指標時,才能以非同步方式執行ReadFile、WriteFileTransactNamedPipeConnectNamedPipe函式。 如果 OVERLAPPED 指標為 Null,則函式傳回值可能會不正確地指出作業已完成。 因此,強烈建議您使用 FILE_FLAG_OVERLAPPED 建立控制碼,而且想要非同步行為,您應該一律指定有效的 OVERLAPPED 結構。

指定之 OVERLAPPED結構的hEvent成員必須包含手動重設事件物件的控制碼。 這是 CreateEvent 函式所建立的同步處理物件。 起始重迭作業的執行緒會使用 事件物件來判斷作業何時完成。 當您在相同的控制碼上執行同時作業時,不應該使用管道控制碼進行同步處理,因為無法知道哪個作業完成導致管道控制碼收到訊號。 在相同管道控點上執行同時作業的唯一可靠技術,是針對每個作業使用個別 的 OVERLAPPED 結構與自己的事件物件。 如需事件物件的詳細資訊,請參閱 同步處理

此外,您可以使用 GetQueuedCompletionStatusGetQueuedCompletionStatusEx 函 式,在重迭的作業完成時收到通知。 在此情況下,您不需要在 OVERLAPPED 結構中指派手動重設事件,而且管道控制碼的完成方式與非同步讀取或寫入作業相同。 如需詳細資訊,請參閱 I/O 完成埠

以非同步方式執行ReadFile、WriteFileTransactNamedPipe 和 ConnectNamedPipe作業時,會發生下列其中一項:

  • 如果函式傳回時作業已完成,則傳回值會指出作業的成功或失敗。 如果發生錯誤,則傳回值為零,而 GetLastError 函 式會傳回ERROR_IO_PENDING以外的專案。
  • 如果函式傳回時作業尚未完成,則傳回值為零,而 GetLastError 會傳回ERROR_IO_PENDING。 在此情況下,呼叫執行緒必須等到作業完成為止。 呼叫執行緒接著必須呼叫 GetOverlappedResult 函式來判斷結果。

使用完成常式

ReadFileExWriteFileEx函式提供另一種重迭的 I/O 形式。 不同于使用事件物件來發出完成訊號的 重迭 ReadFileWriteFile 函式,擴充函式會指定 完成常式。 完成常式是在讀取或寫入作業完成時排入佇列以供執行的函式。 在呼叫ReadFileExWriteFileEx的執行緒呼叫其中一個可警示的等候函式,並將 fAlertable參數設定為TRUE,以啟動可警示的等候作業,才會執行完成常式。 在可警示的等候作業中,當 ReadFileExWriteFileEx 完成常式排入佇列以供執行時,函式也會傳回。 管道伺服器可以使用擴充函式,為每個連線到它的用戶端執行一連串的讀取和寫入作業。 序列中的每個讀取或寫入作業都會指定完成常式,而每個完成常式都會起始序列中的下一個步驟。 如需範例,請參閱 使用完成常式的具名管道伺服器