public class AsyncEnumerator {
public AsyncEnumerator();
public void Execute(IEnumerator<Int32> enumerator); // 外部呼叫
public AsyncCallback End(); // 迭代器內呼叫
public IAsyncResult DequeueAsyncResult(); // 迭代器內呼叫
}
IEnumerator<Int32>,參數含 AsyncEnumerator ae 參考。BeginXxx(..., ae.End(), null) 啟動。yield return N(N 為發起作業數),暫停迭代器。AsyncEnumerator 內部回調將 IAsyncResult 放入收件箱。ae.DequeueAsyncResult() 取出結果供 EndXxx 使用。
private static IEnumerator<Int32> ApmPatternWithIterator(AsyncEnumerator ae, String pathname) {
using (FileStream fs = new FileStream(pathname, FileMode.Open, FileAccess.Read, FileShare.Read, 8192, FileOptions.Asynchronous)) {
Byte[] data = new Byte[fs.Length];
fs.BeginRead(data, 0, data.Length, ae.End(), null);
yield return 1;
Int32 bytesRead = fs.EndRead(ae.DequeueAsyncResult());
ProcessData(data);
}
}
foreach 無法直接驅動此迭代器(會連續執行不暫停),必須透過 AsyncEnumerator.Execute 智慧排程,讓不同執行緒池執行緒在不同時刻執行各段代碼,確保僅在非同步 I/O 完成後繼續。