Promise equivalent in C#

C#PromiseAsync AwaitTaskFuture

C# Problem Overview


In Scala there is a Promise class that could be used to complete a Future manually. I am looking for an alternative in C#.

I am writing a test and I want it to look it similar to this:

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

I understand that this is probably not the right pattern for C#, but I couldn't figure out a reasonable way to achieve the same thing even with somewhat different pattern.

EDIT: please note, that async/await doesn't help here, as I don't have a Task to await! I just have an access to a handler that will be run on another thread.

C# Solutions


Solution 1 - C#

In C#:

  • Task<T> is a future (or Task for a unit-returning future).
  • TaskCompletionSource<T> is a promise.

So your code would translate as such:

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

The "timed asynchronous wait" is a bit awkward, but it's also relatively uncommon in real-world code. For unit tests, I would just do a regular asynchronous wait:

var promise = new TaskCompletionSource<MyResult>();

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

var myResult = await promise.Task;

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

Solution 2 - C#

The rough C# equivalent without third-party libraries would be:

// 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);
}

Note that it is usually best to use the await/async to as high a level as possible. Accessing the Result of a Task or using Wait can in some cases introduce deadlocks.

Solution 3 - C#

You can use C# Promises library

Open sourced on Github: https://github.com/Real-Serious-Games/C-Sharp-Promise

Available on NuGet: https://www.nuget.org/packages/RSG.Promise/

Solution 4 - C#

This is the old school way of doing Promises.
Back then i believe it was called synchronization :)

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

Just for Completeness - to large for a comment.
I agree with Stephen Cleary's answer.

But if you are building a facade around some legacy code this can be used to wrap old API's in a Task like:

public Task<MyResult> GetResultAsync() {
    MyResult result = null;
    var are = new AutoResetEvent(false);
    handlerMyEventsWithHandler(msg => {
        result = msg;
        are.Set();
    });
    are.WaitOne();
    return Task.FromResult(result);
}

Solution 5 - C#

Try looking into the async model. Tasks are the nearest equivalent in c#.

Here's a link to an MS Article explaining their use.

Solution 6 - C#

You can download future(https://www.nuget.org/packages/Future/) package from Nuget and can be used as below

        Promise<int> promise = new Promise<int>();
        new Task(() =>
        {
            Thread.Sleep(100);
            promise.Set(20);

        }).Start();
        int result=promise.Get();

As per the example you can create a promise object and do a get to get result, get will wait until result is on the object. You do a set from another thread as show in the above example.

This package provides the below two classes

  1. Promise : Which waits indefinitely for the result

  2. TimedPromise : Which waits for the result only till the specified time. If result is not available with in the time, it throws timeout exception

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioneddyP23View Question on Stackoverflow
Solution 1 - C#Stephen ClearyView Answer on Stackoverflow
Solution 2 - C#Dark FalconView Answer on Stackoverflow
Solution 3 - C#Mathew SachinView Answer on Stackoverflow
Solution 4 - C#Florian FidaView Answer on Stackoverflow
Solution 5 - C#Rich LinnellView Answer on Stackoverflow
Solution 6 - C#KumareshanView Answer on Stackoverflow