这段代码中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;
}
答案 0 :(得分:1)
由于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
对象发回,您的代码可以进一步处理。这假设你并不特别想要在回调中运行其余的代码,用于线程目的或任何东西,并将返回到主代码流来完成剩下的工作。如果需要,您也可以在回调中进行处理。