Under the covers, the await functionality installs a callback on the task by using a continuation. This callback resumes the asynchronous method at the point of suspension.
The purpose of the synchronization model implemented by this class is to allow the internal asynchronous/synchronous operations of the common language runtime to behave properly with different synchronization models.
Task.Yield usage. As you can see below, for loop is called under async concept. Even loop iterations are running on separate threads, still they are running in an order.
Creates an awaitable task that asynchronously yields back to the current context when awaited. You can use await Task.Yield(); in an asynchronous method to force the method to complete asynchronously. Do not rely on await Task.Yield(); to keep a UI responsive.
When you use async/await, there is no guarantee that the method you call when you do await FooAsync() will actually run asynchronously. The internal implementation is free to return using a completely synchronous path.
If you’re making an API where it’s critical that you don’t block and you run some code asynchronously, and there’s a chance that the called method will run synchronously (effectively blocking), using await Task.Yield() will force your method to be asynchronous, and return control at that point. The rest of the code will execute at a later time (at which point, it still may run synchronously) on the current context.
This can also be useful if you make an asynchronous method that requires some “long running” initialization, ie:
Without the Task.Yield() call, the method will execute synchronously all the way up to the first call to await.
For a non-UI thread with no synchronization context, await Task.Yield() just switches the continuation to a random pool thread. There is no guarantee it is going to be a different thread from the current thread, it’s only guaranteed to be an asynchronous continuation. If ThreadPool is starving, it may schedule the continuation onto the same thread.
In ASP.NET, doing await Task.Yield() doesn’t make sense at all, except for the workaround mentioned in @StephenCleary’s answer. Otherwise, it will only hurt the web app performance with a redundant thread switch.
So, is await Task.Yield() useful? IMO, not much. It can be used as a shortcut to run the continuation via SynchronizationContext.Post or ThreadPool.QueueUserWorkItem, if you really need to impose asynchrony upon a part of your method.
Use the FromResult<TResult> method in scenarios where data may already be available and just needs to be returned from a task-returning method lifted into a Task<TResult>:
Consider a case where you’re downloading images from the web and processing each image (for example, adding the image to a UI control). You have to do the processing sequentially on the UI thread, but you want to download the images as concurrently as possible. Also, you don’t want to hold up adding the images to the UI until they’re all downloaded—you want to add them as they complete:
The general pattern for implementing the cooperative cancellation model is:
- Instantiate a CancellationTokenSource object, which manages and sends cancellation notification to the individual cancellation tokens.
- Pass the token returned by the CancellationTokenSource.Token property to each task or thread that listens for cancellation.
- Call the CancellationToken.IsCancellationRequested method from operations that receive the cancellation token. Provide a mechanism for each task or thread to respond to a cancellation request. Whether you choose to cancel an operation, and exactly how you do it, depends on your application logic.
- Call the CancellationTokenSource.Cancel method to provide notification of cancellation. This sets the CancellationToken.IsCancellationRequested property on every copy of the cancellation token to true.
Call the Dispose method when you are finished with the CancellationTokenSource object.
All public and protected members of CancellationTokenSource are thread-safe and may be used concurrently from multiple threads, with the exception of Dispose, which must only be used when all other operations on the CancellationTokenSource object have completed.
Real life scenarios for using TaskCompletionSource<T>?
The CancellationToken is a struct so many copies could exist due to passing it along to methods. The CancellationTokenSource sets the state of ALL copies of a token when calling Cancel on the source.
Convert synchronous zip operation to async
An ExecutionContext that is associated with a thread cannot be set on another thread. Attempting to do so will result in an exception being thrown. To propagate the ExecutionContext from one thread to another, make a copy of the ExecutionContext.
It’s important to make a distinction between two different types of concurrency. Asynchronous concurrency is when you have multiple asynchronous operations in flight (and since each operation is asynchronous, none of them are actually using a thread). Parallel concurrency is when you have multiple threads each doing a separate operation.
This is an essential truth of async in its purest form: There is no thread.
Some time after the write request started, the device finishes writing. It notifies the CPU via an interrupt. The device driver’s Interrupt Service Routine (ISR) responds to the interrupt. An interrupt is a CPU-level event, temporarily seizing control of the CPU away from whatever thread was running. You could think of an ISR as “borrowing” the currently-running thread, but I prefer to think of ISRs as executing at such a low level that the concept of “thread” doesn’t exist – so they come in “beneath” all threads, so to speak. Anyway, the ISR is properly written, so all it does is tell the device “thank you for the interrupt” and queue a Deferred Procedure Call (DPC).
The task has captured the UI context, so it does not resume the async method directly on the thread pool thread. Instead, it queues the continuation of that method onto the UI context, and the UI thread will resume executing that method when it gets around to it.
Device (Hard Disk) >
Notifies the CPU via an interrupt >
The device driver’s Interrupt Service Routine (ISR) responds to the interrupt
A process requesting I/O services is not notified of completion of the I/O services, but instead checks the I/O completion port’s message queue to determine the status of its I/O requests. The I/O completion port manages multiple threads and their concurrency.
- epoll tells you when a file descriptor is ready to perform a requested operation – such as “you can read from this socket now”.
- IOCP tells you when a requested operation is completed, or failed to complete – such as “the requested read operation has been completed”.
IOCP works by queuing the ReadFile and WriteFile operations, which will complete later. Both read and write operate on buffers, and require the buffers passed to them to be left intact until the operation completes. More, you are not allowed to touch the data in those buffers.
Both epoll and IOCP are suitable for, and typically used to write high performance networking servers handling a large number of concurrent connections.
interrupt handler, also known as an interrupt service routine or ISR, is a callback function in microcontroller firmware, an operating system, or a device driver whose execution is triggered by the reception of an interrupt.
For example, pressing a key on a computer keyboard, or moving the mouse, triggers interrupts that call interrupt handlers which read the key, or the mouse’s position, and copy the associated information into the computer’s memory.
An interrupt handler is a low-level counterpart (same thing) of event handlers.
An interrupt service routine (ISR) is a software routine that hardware invokes in response to an interrupt. ISRs examine an interrupt and determine how to handle it. ISRs handle the interrupt, and then return a logical interrupt value.
A Deferred Procedure Call (DPC) is a Microsoft Windows operating system mechanism which allows high-priority tasks (e.g. an interrupt handler) to defer required but lower-priority tasks for later execution. This permits device drivers and other low-level event consumers to perform the high-priority part of their processing quickly, and schedule non-critical additional processing for execution at a lower priority.
Each processor has a separate DPC queue. DPCs have three priority levels: low, medium and high. DPCs execute directly on the CPU, “beneath” the threading system.
The DPC takes the IRP representing the write request and marks it as “complete”. However, that “completion” status only exists at the OS level; the process has its own memory space that must be notified. So the OS queues a special-kernel-mode Asynchronous Procedure Call (APC) to the thread owning the HANDLE.
The task has captured the UI context, so it does not resume the async method directly on the thread pool thread. Instead, it queues the continuation of that method onto the UI context, and the UI thread will resume executing that method when it gets around to it.
When working with streaming audio or video that uses interrupts, DPCs are used to process the audio in each buffer as they stream in. If another DPC (from a poorly written driver) takes too long and another interrupt generates a new buffer of data, before the first one can be processed, a drop-out results.
An Interrupt Request Level (IRQL) is a hardware independent means with which Windows prioritizes interrupts that come from the system’s processors. On processor architectures which Windows runs on, hardware generates signals which are sent to an interrupt controller. The interrupt controller sends an interrupt request (or IRQ) to the CPU with a certain priority level, and the CPU sets a mask which causes any other interrupts with a lower priority to be put into a pending state, until the CPU releases control back to the interrupt controller. If a signal comes in at a higher priority, then the current interrupt will be put into a pending state, the CPU sets the interrupt mask to the priority and places any interrupts with a lower priority into a pending state until the CPU finishes handling the new, higher priority interrupt.
It’s better to think of an async operation as a ‘message’ that gets passed around, and that message changes forms several times (i.e. from a system call => IRP => APC => UI Dispatcher Queue item). Every time this message is processed, it ends up changing forms.
Now everything is at the mercy of the Device Driver programmer to SpinLock the right memory locations and coordinate all the literally non-time sliced but actually simultaneous DPC’s so that I/O completes without incident and starts the more orderly sequence nicely described in the article to return to Windows Userland.
The idea that “there must be a thread somewhere processing the asynchronous operation” is not the truth.
Free your mind. Do not try to find this “async thread” — that’s impossible. Instead, only try to realize the truth: There is no thread.
If you have CPU-bound code to run, then that code has to run on a thread.
Now, you can push the CPU-bound code to a thread pool thread (e.g., `Task.Run`) and then await it from the UI thread so that your UI thread is not blocked. But that’s not an actual asynchronous operation – it’s a synchronous operation on another thread.
A method marked as “async” may only become asynchronous when it performs an “await“. I assume at the end of your call chain, you’d have an async method without an await – and the compiler will warn you that it will execute synchronously.
The core idea to keep in mind is that a method should only be marked “async” if it has asynchronous work to do. If the method only has synchronous work to do, then it should have a synchronous API, not an asynchronous (Task-returning) one. So, in your example, the entire call chain should be synchronous, not asynchronous.
However, when you’re consuming an API, the situation is a bit different. An API method is either asynchronous or synchronous, and there’s nothing you can do as a consumer to change the nature of the API. So if you have a blocking API, you can’t consume it asynchronously – that doesn’t make sense. If you’re writing a UI app, you have the option of pushing the blocking to a background thread, but since it’s the actual API implementation that does the blocking, you can’t entirely avoid the blocking.
When a completion packet is released to a thread, the system releases the last (most recent) thread associated with that port, passing it the completion information for the oldest I/O completion. A single thread can be associated with, at most, one I/O completion port.
An I/O completion port is associated with the process that created it and is not sharable between processes. However, a single handle is shareable between threads in the same process.
The extra threads appear to be useless and never run, but that assumes that the running thread never gets put in a wait state by some other mechanism, terminates, or otherwise closes its associated I/O completion port. Consider all such thread execution ramifications (a consequence of an action or event, especially when complex or unwelcome) when designing the application.
Good rule of thumb is to have a minimum of twice as many threads in the thread pool as there are processors on the system. It means if you have 4 core computers, you should have at least 8 threads in the pool.
A process has a virtual address space, executable code, open handles to system objects, a security context, a unique process identifier, environment variables, a priority class, minimum and maximum working set sizes, and at least one thread of execution. Each process is started with a single thread, often called the primary thread, but can create additional threads from any of its threads.
The thread context includes the thread’s set of machine registers, the kernel stack, a thread environment block, and a user stack in the address space of the thread’s process. Threads can also have their own security context, which can be used for impersonating clients.
Preemptive multitasking is task in which a computer operating system uses some criteria to decide how long to allocate to any one task before giving another task a turn to use the operating system. The act of taking control of the operating system from one task and giving it to another task is called preempting.
Microsoft Windows supports preemptive multitasking, which creates the effect of simultaneous execution of multiple threads from multiple processes. On a multiprocessor computer, the system can simultaneously execute as many threads as there are processors on the computer.
An application can use the thread pool to reduce the number of application threads and provide management of the worker threads.
The length of the time slice depends on the operating system and the processor. Because each time slice is small (approximately 20 milliseconds), multiple threads appear to be executing at the same time. This is actually the case on multiprocessor systems, where the executable threads are distributed among the available processors. However, you must use caution when using multiple threads in an application, because system performance can decrease if there are too many threads.
It is typically more efficient for an application to implement multitasking by creating a single, multithreaded process, rather than creating multiple processes, for the following reasons:
- The system can perform a context switch more quickly for threads than processes, because a process has more overhead than a thread does (the process context is larger than the thread context).
- All threads of a process share the same address space and can access the process’s global variables, which can simplify communication between threads.
- All threads of a process can share open handles to resources, such as files and pipes.
Summary: Single Process Multiple Threads > Multiple Process Single or Multiple Threads.
The recommended guideline is to use as few threads as possible, thereby minimizing the use of system resources. This improves performance. Multitasking has resource requirements and potential conflicts to be considered when designing your application.
A stack is freed when its thread exits. It is not freed if the thread is terminated by another thread.
For the threads of a single process, critical-section objects provide a more efficient means of synchronization than mutexes. A critical section is used like a mutex to enable one thread at a time to use the protected resource.
Entity Framework async features are there to support an asynchronous programming model, not to enable parallelism.
Func<T, TResult> Delegate
Encapsulates a method that has one parameter and returns a value of the type specified by the TResult parameter.
A lambda expression is an anonymous function that you can use to create delegates or expression tree types. By using lambda expressions, you can write local functions that can be passed as arguments or returned as the value of function calls. Lambda expressions are particularly helpful for writing LINQ query expressions.
Provides functionality to evaluate queries against a specific data source wherein the type of the data is not specified.
The IQueryable<T> interface is intended for implementation by query providers.
Provides the base class from which the classes that represent expression tree nodes are derived. It also contains static factory methods to create the various node types. This is an abstract class.
The following code example shows how to create a block expression. The block expression consists of two MethodCallExpression objects and one ConstantExpression object.
The expression tree is an in-memory data representation of the lambda expression. The expression tree makes the structure of the lambda expression transparent and explicit. You can interact with the data in the expression tree just as you can with any other data structure.
Why would you use Expression<Func<T>> rather than Func<T>?
Func<> will be converted to a method on the c# compiler level ,Expression<Func<>> will be executed on the MSIL level after compiling the code directly, that is the reason it is faster. An expression simply turns a delegate into a data about itself.
The fix was simply to turn Func<T, bool> into Expression<Func<T, bool>>, so I googled why it needs an Expression instead of Func, ending up here.
Func didn’t work because my DbContext was blind to what was actually in the lambda expression to turn it into SQL, so it did the next best thing and iterated that conditional through each row in my table.
Func<string, int> length = s => s.Length;
But we can wrap our “Func<string,int>” in an Expression<T> like this:
Expression<Func<string, int>> length = s => s.Length;
But now we can’t call it anymore. Why is that? Well, “length” is no longer a delegate, but instead it is an expression tree. An expression tree is simply a tree structure that represents the lambda “s => s.Length”. Instead of the C# compiler turning this into an executable method, it simply goes through the syntax and forms a tree that expresses what the lambda is doing.
In fact, there is a method on the Expression type called “Compile” that lets us turn this expression tree into a Func<string, int> that we can run:
Func<string,int> lengthMethod = length.Compile();
int stringLength = lengthMethod(myString);
The Where extension method has two flavors. One extends IQueryable and takes an Expression parameter. The other extends IEnumerable and takes a Func.
You can use a lambda expression anywhere you can use a delegate.
IEnumerable<T> is great for working with sequences that are iterated in-memory, but
IQueryable<T> allows for out-of memory things like a remote data source, such as a database or web service.
The difference is that IQueryable<T> is the interface that allows LINQ-to-SQL (LINQ.-to-anything really) to work. So if you further refine your query on an IQueryable<T>, that query will be executed in the database, if possible.
For the IEnumerable<T> case, it will be LINQ-to-object, meaning that all objects matching the original query will have to be loaded into memory from the database.
Observable example (Rx extensions)
You do not need to implement the IObservable<T>/IObserver<T> interfaces yourself. Rx provides internal implementations of these interfaces for you and exposes them through various extension methods provided by the Observable and Observer types.
You do not need to implement the IObservable<T> interface manually to create an observable sequences.
Similarly, you do not need to implement IObserver<T> either to subscribe to a sequence
It’s been a .NET design guideline that in cases like this, where an exception’s propagation needs to be interrupted, it should be wrapped in another exception object.
When an observer subscribes to an observable sequence, the thread calling the Subscribe method can be different from the thread in which the sequence runs till completion. Therefore, the Subscribe call is asynchronous in that the caller is not blocked until the observation of the sequence completes.
For example, the code
var x = Observable.Zip(a,b).Subscribe();
will subscribe x to both sequences a and b. If a throws an error, x will immediately be unsubscribed from b.
Using a timer
Using the ToObservable operator, you can convert a generic enumerable collection to an observable sequence and subscribe to it.
Cold observables start running upon subscription, i.e., the observable sequence only starts pushing values to the observers when Subscribe is called. Values are also not shared among subscribers. This is different from hot observables such as mouse move events or stock tickers which are already producing values even before a subscription is active.
Hot subscription example;
Rx does not aim at replacing existing asynchronous programming models such as .NET events, the asynchronous pattern or the Task Parallel Library.
The Entity Framework DbContext (or LINQ-to-SQL DataContext) is a Unit Of Work implementation. That means that the same DbContext should be used for all operations (both reading and writing) within a single web or service request.
What is the difference between ManualResetEvent and AutoResetEvent in .NET?
Yes. It’s like the difference between a tollbooth and a door. The ManualResetEvent is the door, which needs to be closed (reset) manually. The AutoResetEvent is a tollbooth, allowing one car to go by and automatically closing before the next one can get through.
Forcing developers to cast the value retrieved from a property on the EventArgs is never acceptable.
The lock statement is a good general-purpose tool, but the Interlocked class provides better performance for updates that must be atomic.
Unlike ASP.NET, SQL Server uses only one process that cannot be recycled without taking a database down for an unacceptably long time.
Although it is theoretically possible to write managed code to handle ThreadAbortException, StackOverflowException, and OutOfMemoryException exceptions, expecting developers to write such robust code throughout an entire application is unreasonable.
Process-wide or cross-application domain mutable shared state is extremely difficult to alter safely and should be avoided whenever possible.
Out-of-memory conditions are not rare in SQL Server.
Observable.FromEventPattern and Throttle method.
To make this work on UI thread, use ObserveOnDispatcher() method.
Task.Yield continues on the current synchronization context or on the current TaskScheduler if one is present. Task.Run does not do that. It always uses the thread-pool.
For example Task.Yield would stay on the UI thread.
Avoid Task.Yield. It’s semantics are less clear. The linked answer is a code smell.
Do not throw System.Exception, System.SystemException, System.NullReferenceException, or System.IndexOutOfRangeException intentionally from your own source code.
Quartz basic example
SimpleTrigger is handy if you need ‘one-shot’ execution (just single execution of a job at a given moment in time), or if you need to fire a job at a given time, and have it repeat N times, with a delay of T between executions.
CronTrigger is useful if you wish to have triggering based on calendar-like schedules – such as “every Friday, at noon” or “at 10:15 on the 10th day of every month.”
DisallowConcurrentExecution is an attribute that can be added to the Job class that tells Quartz not to execute multiple instances of a given job definition (that refers to the given job class) concurrently. Notice the wording there, as it was chosen very carefully.
PersistJobDataAfterExecution attribute, you should strongly consider also using the DisallowConcurrentExecution attribute, in order to avoid possible confusion (race conditions) of what data was left stored when two instances of the same job (JobDetail) executed concurrently.
The only type of exception that you should throw from the execute method is the JobExecutionException.
Explicit Interface Implementation
If a class implements two interfaces that contain a member with the same signature, then implementing that member on the class will cause both interfaces to use that member as their implementation. In the following example, all the calls to Paint invoke the same method.
Short version: it breaks encapsulation but it’s a necessary evil that should be kept to a minimum.
So all other things being equal, you shouldn’t have any protected members at all. But that said, if you have too few, then your class may not be usable as a super class, or at least not as an efficient super class. Often you find out after the fact. My philosophy is to have as few protected members as possible when you first write the class. Then try to subclass it. You may find out that without a particular protected method, all subclasses will have to do some bad thing.
And protected data?
Josh Bloch: The same thing, but even more. Protected data is even more dangerous in terms of messing up your data invariants. If you give someone else access to some internal data, they have free reign over it.
There is boxing involved when using explicit implementation of an interface on value types so be aware of the performance cost.
Using explicit implementation to hide the details of IDisposable.
Program in tasks (chores), not threads (cores). Leave the mapping of tasks to threads or processor cores as a distinctly separate operation in your program, preferably an abstraction you are using that handles thread/core management for you. Create an abundance of tasks in your program, or a task that can be spread across processor cores automatically (such as an OpenMP loop). By creating tasks, you are free to create as many as you can without worrying about oversubscription.
Avoid using locks. Simply say “no” to locks. Locks slow programs, reduce their scalability, and are the source of bugs in parallel programs. Make implicit synchronization the solution for your program. When you still need explicit synchronization, use atomic operations. Use locks only as a last resort. Work hard to design the need for locks completely out of your program.