将任务等待与委托组合

本文关键字:组合 任务 等待 | 更新日期: 2023-09-27 18:26:21

这是一个C#问题,尽管代码是使用Xamarin iOS编写的。我想了解如何将Task方法与异步函数和回调委托相结合。因此,在下面的代码示例中,我想调用await ExecuteGetAsync()并等待SendAsynchronousRequest()完成。

private async Task<CustomHttpResponse> ExecuteGetAsync(CustomHttpRequest inRequest)
{
    NSUrlConnection
        .SendAsynchronousRequest(
            (NSUrlRequest)request,
            NSOperationQueue.MainQueue,
            delegate(NSUrlResponse inResponse, NSData inData, NSError inError)
            {
                // Return the response somehow
            });
}

将任务等待与委托组合

您应该像这样使用TaskCompletionSource类:

private Task<CustomHttpResponse> ExecuteGetAsync(CustomHttpRequest inRequest)
{
    var tcs = new TaskCompletionSource<CustomHttpResponse>();
    NSUrlConnection
        .SendAsynchronousRequest(
            (NSUrlRequest)request, //shouldn't this be inRequest?
            NSOperationQueue.MainQueue,
            delegate(NSUrlResponse inResponse, NSData inData, NSError inError)
            {
                bool error = ... //determine if we have an error
                if(error)
                    tcs.SetException(new Exception(".. error message here ..")); //if we have an error, use the SetException method to set the exception for the Task
                else
                {
                    CustomHttpResponse result = ... // if we don't have an error, get result
                    tcs.SetResult(result); //set the result
                }
            });
    return tcs.Task;
}

请注意,该方法不再使用async关键字。

因为您可以访问父作用域,所以可以预先定义结果变量。然后,创建一个等待句柄。当您的代码得到最终响应时,您设置了结果和句柄,并且您的代码在主作用域中返回结果。

private async Task<CustomHttpResponse> ExecuteGetAsync(CustomHttpRequest inRequest)
{
    CustomHttpResponse result = null; // Put initial result here.
    var handle = new AutoResetEvent(false);
    NSUrlConnection
        .SendAsynchronousRequest(
            (NSUrlRequest)request,
            NSOperationQueue.MainQueue,
            delegate(NSUrlResponse inResponse, NSData inData, NSError inError)
            {
                // Return the response somehow
                result = // make your result
                handle.Set();
            });
    handle.WaitOne(10000) // Wait up to 10 seconds for result
    return result;
}