我提供的界面如下:
public interface IFuture<T>
{
FutureState state { get; }
T value { get; }
Exception error { get; }
IFuture<T> OnItem(FutureValueCallback<T> callback);
IFuture<T> OnSuccess(FutureValueCallback<T> callback);
IFuture<T> OnError(FutureErrorCallback callback);
IFuture<T> OnComplete(FutureCallback<T> callback);
}
以下是可用的状态以及代表的代表权限:
public enum FutureState
{
/// <summary>
/// The future hasn't begun to resolve a value.
/// </summary>
Pending,
/// <summary>
/// The future is working on resolving a value.
/// </summary>
Processing,
/// <summary>
/// The future has a value ready.
/// </summary>
Success,
/// <summary>
/// The future failed to resolve a value.
/// </summary>
Error
}
public delegate void FutureCallback<T>(IFuture<T> future);
public delegate void FutureValueCallback<T>(T value);
public delegate void FutureErrorCallback(Exception error);
我希望能够await
继续这个未来。我相信最好的方法是将其转换为Task<T>
。但是您将如何精确地做到这一点?签名是这样的:
public static Task<T> ToAwaitable<T>(IFuture<T> future)
{
//
}
答案 0 :(得分:3)
您不需要将其包装到Task
中,可以使用GetAwaiter()
编辑具有适当await
方法的任何内容。
public class AwaitableFuture<T>
{
private readonly IFuture<T> _future;
public AwaitableFuture(IFuture<T> future)
{
_future = future;
}
public FutureAwaiter<T> GetAwaiter() => new FutureAwaiter<T>(_future);
}
FutureAwaiter<T>
必须是类型T
的等待者。对象是T
的候补者,如果
INotifyCompletion
; bool IsCompleted
get属性; T GetResult()
方法。因此,示例实现为:
public class FutureAwaiter<T> : INotifyCompletion
{
private readonly IFuture<T> _future;
public bool IsCompleted => _future.state == FutureState.Completed;
public FutureAwaiter(IFuture<T> future)
{
_future = future;
}
public void OnCompleted(Action action) => _future.OnCompleted(x => action);
public T GetResult() => _future.value;
}
答案 1 :(得分:1)
根据将来的实现细节,您可以像这样:
AsyncResult
只是Future的包装,它实现了正确的接口并附加到回调。
internal class AsyncResult<T> : IAsyncResult
{
private ManualResetEvent _manualResetEvent = new ManualResetEvent(false);
public object AsyncState => null;
public WaitHandle AsyncWaitHandle => _manualResetEvent;
public bool CompletedSynchronously => false;
public bool IsCompleted { get; private set; }
public T Result { get; private set; }
public Exception Error { get; private set; }
public AsyncResult(IFuture<T> future)
{
future.OnSuccess(result =>
{
Result = result;
IsCompleted = true;
_manualResetEvent.Set();
});
future.OnError(() =>
{
Error = future.error;
IsCompleted = true;
_manualResetEvent.Set();
});
}
}
根据需要将Future
转换为Task
的方法:
public static class FutureExtensions
{
public static Task<T> ToAsync<T>(this IFuture<T> future)
{
var asyncResult = new AsyncResult<T>(future);
var task = Task.Factory.FromAsync(asyncResult, x =>
{
var ar = (AsyncResult<T>)x;
if (ar.Error != null)
{
throw new AggregateException("Task failed.", ar.Error);
}
return ar.Result;
});
return task;
}
}
和示例用法:
internal static class Program
{
public static async Task Main()
{
var future = new Future(success: true);
var result = await future.ToAsync();
Console.WriteLine(result);
var future2 = new Future(success: false);
try
{
var result2 = await future2.ToAsync();
}
catch (AggregateException e)
{
Console.WriteLine(e.InnerException.Message);
}
}
}