Async Patterns Guide
How to use EFM's async functions for non-blocking file I/O.
Why Use Async?
Synchronous file operations block the game thread, causing frame hitches. Use async operations for:
- Loading large files
- Saving game state during gameplay
- Downloading content from the web
- Batch operations on many files
Async Read
Read as Bytes
AsyncReadFile(Self, FilePath, OnComplete)
OnComplete(bSuccess, Data):
if bSuccess:
ProcessBytes(Data)
else:
HandleError("Failed to read: " + FilePath)
Read as String
AsyncReadFileAsString(Self, FilePath, OnComplete)
OnComplete(bSuccess, Content):
if bSuccess:
ParseConfig(Content)
else:
LoadDefaultConfig()
Async Write
Write Bytes
AsyncWriteFile(Self, FilePath, ByteData, OnComplete)
OnComplete(bSuccess, WrittenPath):
if bSuccess:
Log("Saved to: " + WrittenPath)
else:
LogError("Failed to save")
Write String
AsyncWriteString(Self, FilePath, JsonString, OnComplete)
OnComplete(bSuccess, WrittenPath):
if bSuccess:
OnSaveComplete()
else:
OnSaveFailed()
Async Copy/Move
Copy
AsyncCopyFile(Self, SourcePath, DestPath, OnComplete)
OnComplete(bSuccess, Source, Destination):
if bSuccess:
Log("Copied: " + Source + " -> " + Destination)
else:
LogError("Copy failed")
Move
AsyncMoveFile(Self, SourcePath, DestPath, OnComplete)
OnComplete(bSuccess, Source, Destination):
if bSuccess:
Log("Moved: " + Source + " -> " + Destination)
Chaining Async Operations
Read, modify, and write back:
// Step 1: Read
AsyncReadFileAsString(Self, ConfigPath, OnReadComplete)
OnReadComplete(bSuccess, Content):
if not bSuccess:
Content = CreateDefaultConfig()
// Step 2: Modify
ModifiedContent = UpdateConfig(Content, NewValues)
// Step 3: Write
AsyncWriteString(Self, ConfigPath, ModifiedContent, OnWriteComplete)
OnWriteComplete(bSuccess2, WrittenPath):
if bSuccess2:
Log("Config saved")
else:
LogError("Failed to save config")
Download with Progress
DownloadFile(
Self,
"https://example.com/update.zip",
GetGameSavedDirectory() + "update.zip",
OnProgress(URL, ProgressPercent, BytesDownloaded):
// Update UI
ProgressBar.SetPercent(ProgressPercent / 100.0)
StatusText.SetText(
"Downloading: " + FormatBytes(BytesDownloaded)
),
OnComplete(bSuccess, URL, SavedPath):
if bSuccess:
StatusText.SetText("Download complete!")
InstallUpdate(SavedPath)
else:
StatusText.SetText("Download failed")
RetryButton.SetVisibility(Visible)
)
Batch Operations with Progress
BatchCopyFiles(
Self,
SourceFiles,
DestFiles,
OnProgress(CurrentIndex, TotalCount, CurrentFile, bSuccess):
Percent = (CurrentIndex + 1) / TotalCount * 100
ProgressBar.SetPercent(Percent / 100.0)
StatusText.SetText(
CurrentIndex + 1 + "/" + TotalCount + ": " + CurrentFile
),
OnComplete(bAllSuccess, SuccessCount, FailedCount):
if bAllSuccess:
StatusText.SetText("All " + SuccessCount + " files copied!")
else:
StatusText.SetText(
SuccessCount + " succeeded, " + FailedCount + " failed"
)
)
Best Practices
- Always handle the failure case - async operations can fail due to permissions, disk space, network issues
- Show progress to the user - use the progress callbacks for long operations
- Don't block waiting for async - use the callback pattern, not polling
- Cancel downloads when appropriate - use
CancelDownload(URL)when the user navigates away - Use async for save games - avoid frame hitches during gameplay