TFuture和 TPromise是生产者-消费者模式的经典实现,让一个线程生产结果,另一个线程消费结果。下面详细说明它们的配对使用方式:
基本使用模式
1. 基础示例:简单值传递
1. 基础示例:简单值传递
#include "Async/Async.h"
// 创建Promise
TPromise<int32> Promise;
// 从Promise获取Future
TFuture<int32> Future = Promise.GetFuture();
// 在另一个线程设置值
Async(EAsyncExecution::Thread, [Promise = MoveTemp(Promise)]() mutable {
FPlatformProcess::Sleep(1.0f); // 模拟耗时操作
int32 Result = 100;
Promise.SetValue(Result); // 设置结果
// 或 Promise.SetValue(42);
});
// 在主线程获取结果
if (Future.WaitFor(FTimespan::FromSeconds(2))) { // 等待2秒
int32 Value = Future.Get(); // 获取值
UE_LOG(LogTemp, Log, TEXT("Result: %d"), Value);
} else {
UE_LOG(LogTemp, Warning, TEXT("Timeout!"));
}
2. 完整工作流
// 创建一个计算服务
class FCalculationService {
public:
TFuture<int32> CalculateSum(const TArray<int32>& Numbers) {
TPromise<int32> Promise = TPromise<int32>::Create();
TFuture<int32> Future = Promise.GetFuture();
// 将Promise的所有权转移给工作线程
Async(EAsyncExecution::ThreadPool,
[Numbers, Promise = MoveTemp(Promise)]() mutable {
int32 Sum = 0;
for (int32 Num : Numbers) {
Sum += Num;
}
// 计算完成,设置结果
Promise.SetValue(Sum);
}
);
return Future; // 返回Future给调用者
}
};
// 使用
FCalculationService Service;
TFuture<int32> SumFuture = Service.CalculateSum({1, 2, 3, 4, 5});
// 可以继续做其他事情...
if (SumFuture.IsReady()) {
int32 Result = SumFuture.Get();
UE_LOG(LogTemp, Log, TEXT("Sum: %d"), Result);
}
高级用法
3. 处理复杂对象
// 处理自定义结构
struct FProcessedData {
TArray<uint8> Data;
FString Metadata;
double ProcessingTime;
};
TFuture<FProcessedData> ProcessFile(const FString& FilePath) {
TPromise<FProcessedData> Promise = TPromise<FProcessedData>::Create();
TFuture<FProcessedData> Future = Promise.GetFuture();
Async(EAsyncExecution::Thread,
[FilePath, Promise = MoveTemp(Promise)]() mutable {
FProcessedData Result;
// 模拟处理
TArray<uint8> FileData = LoadFile(FilePath);
Result.Data = CompressData(FileData);
Result.Metadata = GenerateMetadata(FilePath);
Result.ProcessingTime = FPlatformTime::Seconds();
// 设置结果
Promise.SetValue(MoveTemp(Result));
}
);
return Future;
}
4. 错误处理
TFuture<UTexture2D*> LoadTextureAsync(const FString& TexturePath) {
TPromise<UTexture2D*> Promise = TPromise<UTexture2D*>::Create();
TFuture<UTexture2D*> Future = Promise.GetFuture();
Async(EAsyncExecution::Thread,
[TexturePath, Promise = MoveTemp(Promise)]() mutable {
try {
UTexture2D* Texture = LoadTextureFromDisk(TexturePath);
if (!Texture) {
throw std::runtime_error("Failed to load texture");
}
Promise.SetValue(Texture);
} catch (const std::exception& e) {
// Future.Get() 会抛出异常
// 或使用 SetValue 传递错误状态
Promise.SetValue(nullptr);
}
}
);
return Future;
}
5. 网络请求包装
// 将HTTP请求包装为Future
TFuture<FHttpResponsePtr> MakeHttpRequest(const FString& URL) {
TPromise<FHttpResponsePtr> Promise = TPromise<FHttpResponsePtr>::Create();
TFuture<FHttpResponsePtr> Future = Promise.GetFuture();
TSharedRef<IHttpRequest> Request = FHttpModule::Get().CreateRequest();
Request->SetURL(URL);
Request->OnProcessRequestComplete().BindLambda(
[Promise = MoveTemp(Promise)](
FHttpRequestPtr Request,
FHttpResponsePtr Response,
bool bSuccess) mutable {
if (bSuccess) {
Promise.SetValue(Response);
} else {
Promise.SetValue(nullptr);
}
}
);
Request->ProcessRequest();
return Future;
}
浙公网安备 33010602011771号