4557 We always imagine that a variable has a value. That is, as soon as a variable is created, it has some value, even if it's a default value. So if you have two variables, x and y, and you want to print the sum, you might code it this way:
WriteLine( x + y );
Now what if a variable's value doesn't exist right away, but will become available at some time in the future. The time in the future can be a long time, a short time or no time, but you don't know. The variable has a .Result
property which will return the value, but blocking until the value is actually available. Let's say variable x
is that type of a variable, so your code would now look like this:
WriteLine( x.Result + y );
In this case, if the value of x
is not yet available, calling the .Result
property will block until it becomes available. Once the value becomes available, then x is "resolved". After x
is resolve, calling x.Result
is immediate.
You can also write code that executes when the value becomes available. For example:
x.ContinueWith( xr => WriteLine( xr.Result + y ) ).Wait();
Same as before, if x
is already resolved, the action is called immediately.
These types of deferred variables are called Promises ( https://en.wikipedia.org/wiki/Futures_and_promises )
Let's create an int
promise. You create a TaskCompletionSource
:
`TaskCompletionSource<int> xTcs = new TaskCompletionSource<int>();`
The int
value doesn't exist yet. The .Task
property of the TaskCompletionSource
holds the deferred variable that's used by the code that needs to access the eventual value. They don't need access to the actual TaskCompletionSource
.
Task<int> x = xTcs.Task;
return x;
Than the client of that will call x.Result
as described earlier.
At some future point to resolve the promise, the code that created the promise will call call SetResult' on the
TaskCompletionSource`
xTcs .SetResult(15);
This resolves the promise. All code that was blocked by x.Result
will become unblocked at this point. After that point, x.Result
is immediate.
Exceptions
You can also cause the promise to fail by calling the SetException()
method instead of SetResult()
. This will cause the exception to be propagated to clients awaiting on the promise.
aa
Any time you have code that requires certain values to have already been retrieved (such as from a network or disk) or calculated (by async / code), using a promise ensures there's dependencies are handled automatically. If code requires a variable value to be resolve, then using a promise ensures that code that needs the value is executed when the actual value exists, and is not executed too early, using default data.