Yahoo Web Search

Search results

  1. Feb 2, 2019 · Here's an example using a JavaScript Promise.all implementation that you may want to replicate in C#: const [ resolvedPromiseOne, resolvedPromiseTwo ] = await Promise.all([ taskOne, taskTwo ]); In C# you can do something very similar with Task.WhenAll (assuming they return the same types).

  2. Nov 29, 2023 · A Promise is an object representing the eventual completion or failure of an async operation. If a function returns a Promise, it doesn’t immediately return a value, but the...

  3. In computer science, future, promise, delay, and deferred refer to constructs used for synchronizing program execution in some concurrent programming languages. They describe an object that acts as a proxy for a result that is initially unknown, usually because the computation of its value is not yet complete.

    • Overview
    • Don't block, await instead
    • Start tasks concurrently
    • Composition with tasks
    • Asynchronous exceptions
    • Await tasks efficiently
    • Next steps

    The Task asynchronous programming model (TAP) provides an abstraction over asynchronous code. You write code as a sequence of statements, just like always. You can read that code as though each statement completes before the next begins. The compiler performs many transformations because some of those statements may start work and return a Task that represents the ongoing work.

    That's the goal of this syntax: enable code that reads like a sequence of statements, but executes in a much more complicated order based on external resource allocation and when tasks are complete. It's analogous to how people give instructions for processes that include asynchronous tasks. Throughout this article, you'll use an example of instructions for making breakfast to see how the async and await keywords make it easier to reason about code that includes a series of asynchronous instructions. You'd write the instructions something like the following list to explain how to make a breakfast:

    1.Pour a cup of coffee.

    2.Heat a pan, then fry two eggs.

    3.Fry three slices of bacon.

    4.Toast two pieces of bread.

    The preceding code demonstrates a bad practice: constructing synchronous code to perform asynchronous operations. As written, this code blocks the thread executing it from doing any other work. It won't be interrupted while any of the tasks are in progress. It would be as though you stared at the toaster after putting the bread in. You'd ignore anyone talking to you until the toast popped.

    Let's start by updating this code so that the thread doesn't block while tasks are running. The await keyword provides a non-blocking way to start a task, then continue execution when that task completes. A simple asynchronous version of the make a breakfast code would look like the following snippet:

    Important

    The total elapsed time is roughly the same as the initial synchronous version. The code has yet to take advantage of some of the key features of asynchronous programming.

    This code doesn't block while the eggs or the bacon are cooking. This code won't start any other tasks though. You'd still put the toast in the toaster and stare at it until it pops. But at least, you'd respond to anyone that wanted your attention. In a restaurant where multiple orders are placed, the cook could start another breakfast while the first is cooking.

    Now, the thread working on the breakfast isn't blocked while awaiting any started task that hasn't yet finished. For some applications, this change is all that's needed. A GUI application still responds to the user with just this change. However, for this scenario, you want more. You don't want each of the component tasks to be executed sequentially. It's better to start each of the component tasks before awaiting the previous task's completion.

    In many scenarios, you want to start several independent tasks immediately. Then, as each task finishes, you can continue other work that's ready. In the breakfast analogy, that's how you get breakfast done more quickly. You also get everything done close to the same time. You'll get a hot breakfast.

    The System.Threading.Tasks.Task and related types are classes you can use to reason about tasks that are in progress. That enables you to write code that more closely resembles the way you'd create breakfast. You'd start cooking the eggs, bacon, and toast at the same time. As each requires action, you'd turn your attention to that task, take care of the next action, then wait for something else that requires your attention.

    You start a task and hold on to the Task object that represents the work. You'll await each task before working with its result.

    Let's make these changes to the breakfast code. The first step is to store the tasks for operations when they start, rather than awaiting them:

    The preceding code won't get your breakfast ready any faster. The tasks are all awaited as soon as they are started. Next, you can move the await statements for the bacon and eggs to the end of the method, before serving breakfast:

    The asynchronously prepared breakfast took roughly 20 minutes, this time savings is because some tasks ran concurrently.

    You have everything ready for breakfast at the same time except the toast. Making the toast is the composition of an asynchronous operation (toasting the bread), and synchronous operations (adding the butter and the jam). Updating this code illustrates an important concept:

    Important

    The composition of an asynchronous operation followed by synchronous work is an asynchronous operation. Stated another way, if any portion of an operation is asynchronous, the entire operation is asynchronous.

    The preceding code showed you that you can use Task or Task objects to hold running tasks. You await each task before using its result. The next step is to create methods that represent the combination of other work. Before serving breakfast, you want to await the task that represents toasting the bread before adding butter and jam. You can represent that work with the following code:

    The preceding method has the async modifier in its signature. That signals to the compiler that this method contains an await statement; it contains asynchronous operations. This method represents the task that toasts the bread, then adds butter and jam. This method returns a Task that represents the composition of those three operations. The main block of code now becomes:

    The previous change illustrated an important technique for working with asynchronous code. You compose tasks by separating the operations into a new method that returns a task. You can choose when to await that task. You can start other tasks concurrently.

    Up to this point, you've implicitly assumed that all these tasks complete successfully. Asynchronous methods throw exceptions, just like their synchronous counterparts. Asynchronous support for exceptions and error handling strives for the same goals as asynchronous support in general: You should write code that reads like a series of synchronous statements. Tasks throw exceptions when they can't complete successfully. The client code can catch those exceptions when a started task is awaited. For example, let's assume that the toaster catches fire while making the toast. You can simulate that by modifying the ToastBreadAsync method to match the following code:

    Run the application after making these changes, and you'll output similar to the following text:

    You'll notice quite a few tasks are completed between when the toaster catches fire and the exception is observed. When a task that runs asynchronously throws an exception, that Task is faulted. The Task object holds the exception thrown in the Task.Exception property. Faulted tasks throw an exception when they're awaited.

    There are two important mechanisms to understand: how an exception is stored in a faulted task, and how an exception is unpackaged and rethrown when code awaits a faulted task.

    When code running asynchronously throws an exception, that exception is stored in the Task. The Task.Exception property is a System.AggregateException because more than one exception may be thrown during asynchronous work. Any exception thrown is added to the AggregateException.InnerExceptions collection. If that Exception property is null, a new AggregateException is created and the thrown exception is the first item in the collection.

    The most common scenario for a faulted task is that the Exception property contains exactly one exception. When code awaits a faulted task, the first exception in the AggregateException.InnerExceptions collection is rethrown. That's why the output from this example shows an InvalidOperationException instead of an AggregateException. Extracting the first inner exception makes working with asynchronous methods as similar as possible to working with their synchronous counterparts. You can examine the Exception property in your code when your scenario may generate multiple exceptions.

    The series of await statements at the end of the preceding code can be improved by using methods of the Task class. One of those APIs is WhenAll, which returns a Task that completes when all the tasks in its argument list have completed, as shown in the following code:

    Another option is to use WhenAny, which returns a Task that completes when any of its arguments complete. You can await the returned task, knowing that it has already finished. The following code shows how you could use WhenAny to await the first task to finish and then process its result. After processing the result from the completed task, you remove that completed task from the list of tasks passed to WhenAny.

    Near the end, you see the line await finishedTask;. The line await Task.WhenAny doesn't await the finished task. It awaits the Task returned by Task.WhenAny. The result of Task.WhenAny is the task that has completed (or faulted). You should await that task again, even though you know it's finished running. That's how you retrieve its result, or ensure that the exception causing it to fault gets thrown.

    After all those changes, the final version of the code looks like this:

    The final version of the asynchronously prepared breakfast took roughly 6 minutes because some tasks ran concurrently, and the code monitored multiple tasks at once and only took action when it was needed.

    This final code is asynchronous. It more accurately reflects how a person would cook a breakfast. Compare the preceding code with the first code sample in this article. The core actions are still clear from reading the code. You can read this code the same way you'd read those instructions for making a breakfast at the beginning of this article. The language features for async and await provide the translation every person makes to follow those written instructions: start tasks as you can and don't block waiting for tasks to complete.

    Explore real world scenarios for asynchronous programs

  4. Oct 12, 2023 · C# has a language-level asynchronous programming model, which allows for easily writing asynchronous code without having to juggle callbacks or conform to a library that supports asynchrony. It follows what is known as the Task-based Asynchronous Pattern (TAP). Overview of the asynchronous model.

  5. Promises return a value at a later time: asynchronously. You simply create an instance and return it from your method. Your async work will then trigger the result via promise.Resolve. You can fail the promise by calling promise.Fail which takes an Exception.

  6. People also ask

  7. Apr 16, 2024 · The caller doesn’t get a result but instead obtains a promise of a result, which is the Task<TResult> object returned by the async method. The caller’s thread can do some work (task B here) and then await the task later when it finally needs the result.

  1. People also search for