这段代码中 async-await 操作的顺序有点偏离。await
里面的任务DownloadMetasBySortAsync
不像我想象的那样表现。任务自行完成,但只有在DownloadMetasBySortAsync
已经返回null
到 之后DownloadMetasAsync
。
我已经尝试添加Task.Wait()
中的任务DownloadMetasAsync
和令人反感的、等待的任务。我试过了ConfigureAwait()
。DownloadMetasBySortAsync
总是null
在所需的任务完成之前退回。
我错过了什么?
public async Task<List<MyMeta>> DownloadMetasAsync(SortType sortType)
{
ResetFlags();
_cloudMetas = await DownloadMetasBySortAsync(sortType);
Debug.Log((_cloudMetas != null) ? _cloudMetas.Count + " metas downloaded" : "NULL cloudmetas");
return _cloudMetas;
}
private async Task<List<MyMeta>> DownloadMetasBySortAsync(SortType sortType)
{
//Load Table
Table dbTable = null;
//Can't call LoadTable from main thread
await Task.Run(() => {
try {
dbTable = Table.LoadTable(DBClient, new TableConfig(_databaseName));
}catch( Exception ex ) {
_operationFailed = true;
ThrowError(ex);
}
});
if(dbTable == null ) { return null; }
//Set up secondary local index if needed
string sortIndex = (sortType == SortType.Creator) ? "date-creator-index" : null;
return await ScanTable(_dbName, sortIndex); //Scan table for list of metas
}
private async Task<List<MyMeta>> ScanTable(string dbName, string index)
{
List<MyMeta> metaList = null;
try {
Dictionary<string,AttributeValue> lastKeyEvaluated = null;
do {
var request = new ScanRequest
{
TableName = dbName,
IndexName = index,
ConsistentRead = true,
ExclusiveStartKey = lastKeyEvaluated
};
Debug.Log("Scanning...");
await Task.Run(() =>
{
DBClient.ScanAsync(request, (responseObj) =>
{
if( responseObj == null ) {
Debug.LogWarning("Response NULL");
}
else {
Debug.Log("Response received");
if(metaList == null ) { metaList = new List<MyMeta>(); }
var resultList = ProcessScanResult(responseObj.Response);
if( resultList != null && resultList.Count > 0 ) {
metaList.AddRange(resultList);
}
}
lastKeyEvaluated = responseObj.Response.LastEvaluatedKey;
});
});
} while( lastKeyEvaluated != null && lastKeyEvaluated.Count != 0 );
}
catch( Exception ex ) {
ThrowError(ex);
}
return metaList;
}
由于DBClient.ScanAsync
不是 async/await 方法而是异步方法的回调类型,因此它会在被调用后立即返回,并且结果只会在稍后出现。要处理此问题,您可以使用TaskCompletionSource
将其变成可等待的东西:
var task = new TaskCompletionSource<responseObjType>();
DBClient.ScanAsync(request, (responseObj) =>
{
task.SetResult(responseObj);
}
// Will wait for the callback to be called before continuing and get the results
var responseObj = await task.Task;
if( responseObj == null )
{
...
这样,该方法将等到回调被调用,数据通过TaskCompletionSource
对象发回,您的代码可以进一步处理它。这假设您不特别想在回调中运行其余代码,用于线程目的或任何其他目的,并且将返回到主代码流来完成其余的工作。如果需要,您也可以在回调中进行处理。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句