所以这就是我正在做的:
var resultObj = GetFirstResultAsync()
.ContinueWith(t => GetSecondResultAsync(resultObj))
.Wait();
本质上告诉我,在声明变量之前我不能使用该变量,因此我得到了我发布的问题。我该怎么做?
这是我的目标,我有一个列表
resultObj
然后在该列表上我将循环遍历ID以获取我想要的另一个列表的数组GetSecondResultAsync
有点深入列表,我想使用异步,因为它将使用 HttpClient
来获取数据。
使用
Task
创建一个具有与第一个任务不同类型结果的延续
ContinueWith
并非易事。您必须使用 Unwrap
方法来展平结果 Task<Task<MySecondResult>>
,仔细处理失败和取消情况,并明确指定 将执行延续的 TaskScheduler
:
Task<MySecondResult> task = GetFirstResultAsync().ContinueWith(t =>
{
if (t.IsFaulted)
{
TaskCompletionSource<MySecondResult> tcs = new();
tcs.SetException(t.Exception.InnerExceptions);
return tcs.Task;
}
if (t.IsCanceled)
{
TaskCompletionSource<MySecondResult> tcs = new();
tcs.SetCanceled(new TaskCanceledException(t).CancellationToken);
return tcs.Task;
}
return GetSecondResultAsync(t.Result);
}, TaskScheduler.Default).Unwrap();
这相当麻烦。您不希望这样的代码频繁出现在您的应用程序代码中。您可以将此功能封装在扩展方法中,例如
thisGitHub 提案中请求的
Then
/ContinueWithResult
扩展方法,或者使用 async/await 代替 ContinueWith
。 Async/await 是可组合的,因此您可以编写第三种 async
方法,将 GetFirstResultAsync
和 GetSecondResultAsync
组合为一个:
async Task<MySecondResult> GetSecondAfterFirstAsync()
{
MyFirstResult result = await GetFirstResultAsync();
return await GetSecondResultAsync(result);
}
您应该能够通过将ContinueWith语句更改为t.Result来传递结果。比如:
var resultObj = GetFirstResultAsync()
.ContinueWith(t => GetSecondResultAsync(t.Result));
我还没有测试过代码。
第一个运行的线程将返回一个“Task”。您必须通过 Task.Result 访问它。这是你必须使用的。
编辑:正如@fahadash所述,不应使用“wait()”。请改用“等待”。