edd*_*P23 57 c# future task promise async-await
在Scala中有一个Promise类,可用于手动完成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);
Run Code Online (Sandbox Code Playgroud)
我知道这可能不是C#的正确模式,但我无法找到一种合理的方法来实现同样的东西,即使是有些不同的模式.
编辑:请注意,这async
//await
没有帮助,因为我没有任务等待!我只能访问将在另一个线程上运行的处理程序.
Ste*_*ary 85
在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);
Run Code Online (Sandbox Code Playgroud)
"定时异步等待"有点尴尬,但它在现实世界的代码中也相对不常见.对于单元测试,我只是做一个常规的异步等待:
var promise = new TaskCompletionSource<MyResult>();
handlerMyEventsWithHandler(msg => promise.TrySetResult(msg));
var myResult = await promise.Task;
Assert.Equals("my header", myResult.Header);
Run Code Online (Sandbox Code Playgroud)
Dar*_*con 11
没有第三方库的粗略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);
}
Run Code Online (Sandbox Code Playgroud)
请注意,通常最好使用await
/ async
to尽可能高的级别.在某些情况下,访问Result
a Task
或使用Wait
can会引入死锁.
您可以使用C#Promises库
在Github上开源:https://github.com/Real-Serious-Games/C-Sharp-Promise
可在NuGet上获取:https://www.nuget.org/packages/RSG.Promise/
这是执行 Promise 的老式方法。
当时我相信这被称为同步:)
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);
Run Code Online (Sandbox Code Playgroud)
只是为了完整性 - 太大的评论。
我同意斯蒂芬·克利里的回答。
但是,如果您正在围绕一些遗留代码构建外观,则可以使用它来将旧 API 包装在任务中,例如:
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);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
41715 次 |
最近记录: |