繁体   English   中英

如何在返回值之前等待回调完成?

[英]How do I wait for the callback to finish before I return the value?

public List<S3Object> ListObjects(string bucketname, string identityId)
{
    List<S3Object> objectList = new List<S3Object>();

    var request = new ListObjectsV2Request()
    {
        BucketName = bucket_name,
        Prefix = identityId
    };

    Client.ListObjectsV2Async(request, (responseObject) =>
    {
        if (responseObject.Exception == null)
        {
            List<S3Object> list = new List<S3Object>();
            responseObject.Response.S3Objects.ForEach((o) =>
            {
                objectList.Add(o);
            });
        }
        else
        {
            Debug.Log(responseObject.Exception);
        }
    });
    //return objectList;         

    // return the object after the callback is finished, e.g. added all the objects into objectList;
    // ListObjectsV2Async method returns void, so it is not possible to use async and await. i guess?
}

我想在 ListObjectsV2Async 方法中的回调完成后返回 objectList 字段。 但是,此方法异步运行,因此如果我只返回列表,它将返回一个空列表。 那么我如何等到回调将所有对象添加到列表中后再返回?

TaskCompletionSource可用于捕获回调的结果,允许方法等待。

例如

public Task<List<S3Object>> ListObjectsAsync(string bucket_name, string identityId) {
    TaskCompletionSource<List<S3Object>> tcs = new TaskCompletionSource<List<S3Object>>();

    var request = new ListObjectsV2Request() {
        BucketName = bucket_name,
        Prefix = identityId
    };

    Client.ListObjectsV2Async(request, (responseObject) => {
        if (responseObject.Exception == null) {
            tcs.TrySetResult(responseObject.Response.S3Objects.ToList());
        } else {
            Debug.Log(responseObject.Exception);
            tcs.TrySetException(responseObject.Exception);
        }
    });

    // return the object after the callback is finished
    return tcs.Task;
}

现在允许

List<S3Object> objectList = await myClient.ListObjectsAsync("bucket_name_here", "identityId_here");

如果您确定不想异步执行操作,那为什么要调用异步版本呢? 改用ListObjectsV2

public List<S3Object> ListObjects(string bucketname, string identityId)
{
    List<S3Object> objectList = new List<S3Object>();

    var request = new ListObjectsV2Request()
    {
        BucketName = bucket_name,
        Prefix = identityId
    };
    
    ListObjectsV2Response responseObject = Client.ListObjectsV2(request);
    
    if (responseObject.Exception == null)
    {
        List<S3Object> list = new List<S3Object>();
        responseObject.Response.S3Objects.ForEach((o) =>
        {
            objectList.Add(o);
        });
    }
    else
    {
        Debug.Log(responseObject.Exception);
    }
    
    return objectList; 
}

Nkosi的答案有一个比本节更优雅的解决方案。 如果您想异步获取对象列表,请参阅他们的回答。

但是,我建议重新设计,以便ListObjects返回 void,采用一个或多个Action<List<S3Object>>参数,然后在回调中调用适当的操作:

public void ListObjects(string bucketname, string identityId,
        Action<List<S3Object>> callbackSuccess, Action callbackFailure)
{
    List<S3Object> objectList = new List<S3Object>();

    var request = new ListObjectsV2Request()
    {
        BucketName = bucket_name,
        Prefix = identityId
    };
    
    Client.ListObjectsV2Async(request, (responseObject) =>
    {
        if (responseObject.Exception == null)
        {
            List<S3Object> list = new List<S3Object>();
            responseObject.Response.S3Objects.ForEach((o) =>
            {
                objectList.Add(o);
            });
            callbackSuccess.Invoke(objectList);
        }
        else
        {
            Debug.Log(responseObject.Exception);
            callbackFailure.Invoke();
        }
    });
}

然后,在调用ListObjects地方,您可以在处理程序中包含您需要的任何局部变量。 就像是:

int localVar1 = 123;
float localVar2 = 4.56f;

Action<List<S3Object>> handleSuccess = (resultList) => 
{
    DoStuffWithList(resultList, localVar1, localVar2);
};
Action handleFailure = () =>
{
    DoStuffWhenFail(localVar1);
};

s3Client.ListObjects("foo", "bar", handleSuccess, handleFailure);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM