繁体   English   中英

C# 中的 Promise 等价物

[英]Promise equivalent in C#

在 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);

我知道这可能不是 C# 的正确模式,但即使使用稍微不同的模式,我也无法找到一种合理的方法来实现相同的目标。

编辑:请注意, async / await在这里没有帮助,因为我没有等待的任务! 我只能访问将在另一个线程上运行的处理程序。

在 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);

“定时异步等待”有点尴尬,但在现实世界的代码中也相对不常见。 对于单元测试,我只会做一个常规的异步等待:

var promise = new TaskCompletionSource<MyResult>();

handlerMyEventsWithHandler(msg => promise.TrySetResult(msg));

var myResult = await promise.Task;

Assert.Equals("my header", myResult.Header);

没有第三方库的粗略 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到尽可能高的级别。 在某些情况下,访问TaskResult或使用Wait可能会导致死锁

您可以使用 C# Promises 库

在 Github 上开源: https : //github.com/Real-Serious-Games/C-Sharp-Promise

在 NuGet 上可用: https : //www.nuget.org/packages/RSG.Promise/

这是做 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);

只是为了完整性 - 大到评论。
我同意Stephen Cleary 的回答

但是如果你正在围绕一些遗留代码构建一个外观,这可以用来将旧的 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);
}

尝试查看异步模型。 任务是 C# 中最接近的等价物。

这是解释它们使用的 MS 文章的链接。

您可以从 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 将等到结果出现在对象上。 你从另一个线程做一组,如上例所示。

这个包提供了以下两个类

  1. Promise :无限期等待结果

  2. TimedPromise :它只在指定的时间等待结果。 如果结果在时间内不可用,则抛出超时异常

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM