您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

147 行
4.8 KiB

using System;
using System.Threading.Tasks;
namespace Unity.Services.Core
{
/// <summary>
/// Set of utility functions added as extensions to
/// <see cref="IAsyncOperation"/> and <see cref="IAsyncOperation{T}"/>.
/// </summary>
static class AsyncOperationExtensions
{
/// <summary>
/// Get a default awaiter on <paramref name="self"/>.
/// </summary>
/// <param name="self">
/// The operation to create an awaiter for.
/// </param>
/// <returns>
/// Return a default awaiter for <paramref name="self"/>.
/// </returns>
/// <remarks>
/// This is required so we can directly use the <see langword="await"/>
/// keyword on an <see cref="IAsyncOperation"/>.
/// </remarks>
public static AsyncOperationAwaiter GetAwaiter(this IAsyncOperation self)
{
return new AsyncOperationAwaiter(self);
}
/// <summary>
/// Get a Task based on <paramref name="self"/>.
/// </summary>
/// <param name="self">
/// The operation to create a Task for.
/// </param>
/// <returns>
/// Return a <see cref="T:System.Threading.Tasks.Task"/>.
/// </returns>
public static Task AsTask(this IAsyncOperation self)
{
if (self.Status == AsyncOperationStatus.Succeeded)
{
return Task.CompletedTask;
}
var taskCompletionSource = new TaskCompletionSource<object>();
void CompleteTask(IAsyncOperation operation)
{
switch (operation.Status)
{
case AsyncOperationStatus.Failed:
taskCompletionSource.TrySetException(operation.Exception);
break;
case AsyncOperationStatus.Cancelled:
taskCompletionSource.TrySetCanceled();
break;
case AsyncOperationStatus.Succeeded:
taskCompletionSource.TrySetResult(null);
break;
default:
throw new ArgumentOutOfRangeException();
}
}
if (self.IsDone)
{
CompleteTask(self);
}
else
{
self.Completed += CompleteTask;
}
return taskCompletionSource.Task;
}
/// <summary>
/// Get a default awaiter for <paramref name="self"/>.
/// </summary>
/// <param name="self">
/// The operation to create an awaiter for.
/// </param>
/// <typeparam name="T">
/// The result's type of <paramref name="self"/>.
/// </typeparam>
/// <returns>
/// Return a default awaiter for <paramref name="self"/>.
/// </returns>
/// <remarks>
/// This is required so we can directly use the <see langword="await"/>
/// keyword on an <see cref="IAsyncOperation{T}"/>.
/// </remarks>
public static AsyncOperationAwaiter<T> GetAwaiter<T>(this IAsyncOperation<T> self)
{
return new AsyncOperationAwaiter<T>(self);
}
/// <summary>
/// Get a Task based on <paramref name="self"/>.
/// </summary>
/// <param name="self">
/// The operation to create a Task for.
/// </param>
/// <typeparam name="T">
/// The result's type of <paramref name="self"/>.
/// </typeparam>
/// <returns>
/// Return a <see cref="T:System.Threading.Tasks.Task`1"/>
/// </returns>
public static Task<T> AsTask<T>(this IAsyncOperation<T> self)
{
var taskCompletionSource = new TaskCompletionSource<T>();
void CompleteTask(IAsyncOperation<T> operation)
{
switch (operation.Status)
{
case AsyncOperationStatus.Succeeded:
taskCompletionSource.TrySetResult(operation.Result);
break;
case AsyncOperationStatus.Failed:
taskCompletionSource.TrySetException(operation.Exception);
break;
case AsyncOperationStatus.Cancelled:
taskCompletionSource.TrySetCanceled();
break;
default:
throw new ArgumentOutOfRangeException();
}
}
if (self.IsDone)
{
CompleteTask(self);
}
else
{
self.Completed += CompleteTask;
}
return taskCompletionSource.Task;
}
}
}