C# 中的 Promise 等价物
Promise equivalent in C#
在 Scala 中有一个 Promise class 可用于手动完成 Future。我正在寻找 C# 中的替代方案。
我正在编写一个测试,我希望它看起来像这样:
// var MyResult has a field `Header`
var promise = new Promise<MyResult>;
handlerMyEventsWithHandler( msg =>
promise.Complete(msg);
);
// Wait for 2 seconds
var myResult = promise.Future.Await(2000);
Assert.Equals("my header", myResult.Header);
我知道这可能不是 C# 的正确模式,但我想不出一个合理的方法来实现同样的事情,即使模式有些不同。
编辑:请注意,async
/await
在这里没有帮助,因为我没有等待的任务!我只能访问将在另一个线程上 运行 的处理程序。
尝试研究异步模型。任务是 c# 中最接近的等价物。
您可以使用 C# Promises 库
在 Github 上开源:https://github.com/Real-Serious-Games/C-Sharp-Promise
在 NuGet 上可用:https://www.nuget.org/packages/RSG.Promise/
没有第三方库的粗略 C# 等效项是:
// var MyResult has a field `Header`
var promise = new TaskCompletionSource<MyResult>();
handlerMyEventsWithHandler(msg =>
promise.SetResult(msg)
);
// Wait for 2 seconds
if (promise.Task.Wait(2000))
{
var myResult = promise.Task.Result;
Debug.Assert("my header" == myResult.Header);
}
请注意,通常最好使用 await
/async
到尽可能高的级别。访问 Task
的 Result
或使用 Wait
在某些情况下可以 introduce deadlocks.
在 C# 中:
Task<T>
是未来(或 Task
是单位回报的未来)。
TaskCompletionSource<T>
是一个承诺。
因此您的代码将这样翻译:
// var promise = new Promise<MyResult>;
var promise = new TaskCompletionSource<MyResult>();
// handlerMyEventsWithHandler(msg => promise.Complete(msg););
handlerMyEventsWithHandler(msg => promise.TrySetResult(msg));
// var myResult = promise.Future.Await(2000);
var completed = await Task.WhenAny(promise.Task, Task.Delay(2000));
if (completed == promise.Task)
; // Do something on timeout
var myResult = await completed;
Assert.Equals("my header", myResult.Header);
"timed asynchronous wait"有点笨拙,但在实际代码中也相对不常见。对于单元测试,我只会做一个常规的异步等待:
var promise = new TaskCompletionSource<MyResult>();
handlerMyEventsWithHandler(msg => promise.TrySetResult(msg));
var myResult = await promise.Task;
Assert.Equals("my header", myResult.Header);
这是做 Promises 的老派方式。
那时我相信它被称为同步:)
MyResult result = null;
var are = new AutoResetEvent(false);
handlerMyEventsWithHandler(
msg => {result = msg; are.Set();}
);
// Wait for 2 seconds
if(!are.WaitOne(2000)) {/* handle timeout... */}
Assert.Equals("my header", myResult.Header);
只是为了完整性 - 大的评论。
我同意。
但是,如果您要围绕一些遗留代码构建外观,这可用于将旧的 API 包装在任务中,例如:
public Task<MyResult> GetResultAsync() {
MyResult result = null;
var are = new AutoResetEvent(false);
handlerMyEventsWithHandler(msg => {
result = msg;
are.Set();
});
are.WaitOne();
return Task.FromResult(result);
}
您可以从 Nuget 下载 future(https://www.nuget.org/packages/Future/) 包,并可以如下使用
Promise<int> promise = new Promise<int>();
new Task(() =>
{
Thread.Sleep(100);
promise.Set(20);
}).Start();
int result=promise.Get();
根据示例,您可以创建一个 promise 对象并执行 get 以获取结果,get 将等到结果出现在对象上。如上例所示,您从另一个线程进行设置。
这个包提供以下两个类
Promise :无限期等待结果
TimedPromise :只在指定时间等待结果。如果结果在时间内不可用,则抛出超时异常
在 Scala 中有一个 Promise class 可用于手动完成 Future。我正在寻找 C# 中的替代方案。
我正在编写一个测试,我希望它看起来像这样:
// var MyResult has a field `Header`
var promise = new Promise<MyResult>;
handlerMyEventsWithHandler( msg =>
promise.Complete(msg);
);
// Wait for 2 seconds
var myResult = promise.Future.Await(2000);
Assert.Equals("my header", myResult.Header);
我知道这可能不是 C# 的正确模式,但我想不出一个合理的方法来实现同样的事情,即使模式有些不同。
编辑:请注意,async
/await
在这里没有帮助,因为我没有等待的任务!我只能访问将在另一个线程上 运行 的处理程序。
尝试研究异步模型。任务是 c# 中最接近的等价物。
您可以使用 C# Promises 库
在 Github 上开源:https://github.com/Real-Serious-Games/C-Sharp-Promise
在 NuGet 上可用:https://www.nuget.org/packages/RSG.Promise/
没有第三方库的粗略 C# 等效项是:
// var MyResult has a field `Header`
var promise = new TaskCompletionSource<MyResult>();
handlerMyEventsWithHandler(msg =>
promise.SetResult(msg)
);
// Wait for 2 seconds
if (promise.Task.Wait(2000))
{
var myResult = promise.Task.Result;
Debug.Assert("my header" == myResult.Header);
}
请注意,通常最好使用 await
/async
到尽可能高的级别。访问 Task
的 Result
或使用 Wait
在某些情况下可以 introduce deadlocks.
在 C# 中:
Task<T>
是未来(或Task
是单位回报的未来)。TaskCompletionSource<T>
是一个承诺。
因此您的代码将这样翻译:
// var promise = new Promise<MyResult>;
var promise = new TaskCompletionSource<MyResult>();
// handlerMyEventsWithHandler(msg => promise.Complete(msg););
handlerMyEventsWithHandler(msg => promise.TrySetResult(msg));
// var myResult = promise.Future.Await(2000);
var completed = await Task.WhenAny(promise.Task, Task.Delay(2000));
if (completed == promise.Task)
; // Do something on timeout
var myResult = await completed;
Assert.Equals("my header", myResult.Header);
"timed asynchronous wait"有点笨拙,但在实际代码中也相对不常见。对于单元测试,我只会做一个常规的异步等待:
var promise = new TaskCompletionSource<MyResult>();
handlerMyEventsWithHandler(msg => promise.TrySetResult(msg));
var myResult = await promise.Task;
Assert.Equals("my header", myResult.Header);
这是做 Promises 的老派方式。
那时我相信它被称为同步:)
MyResult result = null;
var are = new AutoResetEvent(false);
handlerMyEventsWithHandler(
msg => {result = msg; are.Set();}
);
// Wait for 2 seconds
if(!are.WaitOne(2000)) {/* handle timeout... */}
Assert.Equals("my header", myResult.Header);
只是为了完整性 - 大的评论。
我同意
但是,如果您要围绕一些遗留代码构建外观,这可用于将旧的 API 包装在任务中,例如:
public Task<MyResult> GetResultAsync() {
MyResult result = null;
var are = new AutoResetEvent(false);
handlerMyEventsWithHandler(msg => {
result = msg;
are.Set();
});
are.WaitOne();
return Task.FromResult(result);
}
您可以从 Nuget 下载 future(https://www.nuget.org/packages/Future/) 包,并可以如下使用
Promise<int> promise = new Promise<int>();
new Task(() =>
{
Thread.Sleep(100);
promise.Set(20);
}).Start();
int result=promise.Get();
根据示例,您可以创建一个 promise 对象并执行 get 以获取结果,get 将等到结果出现在对象上。如上例所示,您从另一个线程进行设置。
这个包提供以下两个类
Promise :无限期等待结果
TimedPromise :只在指定时间等待结果。如果结果在时间内不可用,则抛出超时异常