Delegate defines a type, the instance of this type can refer some function. It is immutable.

MultiCast delegates – can call group of methods, in the same order as methods were added to group (by +=, -=, but it creates new instance).

If there are return values within methods of multicast delegates – caller obtain the last delegate call result.

Instance method delegate – should be supplied (by assigning to <delegate instance field>.Target) with reference to object instance which is used to call method.

Delegate can have generic type

Delegate Compatibility

Delegate types are all incompatible with each other, even if their signatures are the

same, but D2 d2 = new D2 (d1);

Delegates are equal in case the refer the same method.

Delegate Parameter compatibility (contravariance)

Delegate type can have more concrete parameter that function that will be pointed by delegate instance. It is for parameters and return value.

Generic delegates

The same as generic interface

Events

Language entity that implements an idea of broadcaster and subscribers.

Broadcaster call an event like a function.

Can be fired only from a class that declare it.

Event can be only += (added) or -= (deleted) with some new subscriber, but could not be assigned. It prevent overriding other already subscribed recipients.

Event can be an interface member, delegate is not.

System.EventArgs – superclass for all arguments passed into delegate.

Three rules for Framework compatible delegate:

– It must have a void return type.

– It must accept two arguments: the first of type object, and the second a subclass of EventArgs. The first argument indicates the event broadcaster, and the second argument contains the extra information to convey.

– Its name must end with EventHandler.

Event Accessors – += ad -=

Compiler defines default, but it is possible to redefine it by custom implementation.

Events can be virtual, overridden, abstract, or sealed, static.

Lambda

Unnamed method converted into delegate or expression tree by compiler

(parameters) => expression-or-statement-block

Lambda statement can capture outer variables (captured variables), such lambda is called closure.

Captured variables are evaluated while calling not while capturing.

Lifetime of any variable capture by lambda is extended to corresponding delegate.

Local variable instantiated within labda is instantiated each call for this lambda.

Capturing iteration variables: compiler makes the iteration variable declared within loop, so while calling delegate variable will have the last loop value. To have several different iteration variables captured, you need to assign iteration variable to local variable and then capture the local variable.

Anonymous methods – ancestor of lambda, obsolete.

try-catch-finally keywords

Try must be followed by catch block or finally or both. Catch executes if error occurs, finally executes at any case after try or catch block.

try

{

… // exception may get thrown within execution of this block

}

catch (ExceptionA ex)

{

… // handle exception of type ExceptionA

}

catch (ExceptionB ex)

{

… // handle exception of type ExceptionB

}

finally

{

… // cleanup code

}

Exception handling is quite expensive.

Catch param should be Exception type or its subtype.

Only on catch block is executed for one exception

Catch(…) is used for C++ exceptions that might be not inherited from Exception, in this case it is wrapped by CLR by RuntimeWrappedException.

An operator is overloaded by declaring an operator function. An operator function

has the following rules:

– The name of the function is specified with the operator keyword followed by

an operator symbol.

– The operator function must be marked static and public.

– The parameters of the operator function represent the operands.

– The return type of an operator function represents the result of an expression.

– At least one of the operands must be the type in which the operator function is

declared.

Extension methods

Extension methods allow an existing type to be extended with new methods without altering the definition of the original type. An extension method is a static method of a static class, where the this modifier is applied to the first parameter. The type of the first parameter will be the type that is extended.

For example:

public static class StringHelper

{

public static bool IsCapitalized (this string s)

{

if (string.IsNullOrEmpty(s)) return false;

return char.IsUpper (s[0]);

}

}

Interfaces can be extended too.

Extension method chain

public static class StringHelper

{

public static string Pluralize (this string s) {…}

public static string Capitalize (this string s) {…}

}

string x = “sausage”.Pluralize().Capitalize();

Instance method will always take precedence over an extension method.

In case of two extension methods the more specific method takes precedence.

Comparison between two anonymous types is implemented comparison between members.

Array of anonymous types instancies

var dudes = new[]

{

new { Name = “Bob”, Age = 30 },

new { Name = “Tom”, Age = 40 }

};

Dynamic Binding

Static binding – method is found by following sequence:

Duck d = …

d.Quack();

– method named Quack on Duck.

– method named Quack with optional parameters on Duck.

– methods on base classes of Duck

– extension methods that take Duck as its first parameter

Dynamic Binding – method is found in runtime in same sequence as while static binding (if not found RuntimeBinderException is thrown)

dynamic d = GetSomeObject();

d.Quack();

Custom Binding – When dynamic object implements IDynamicMetaObjectProvider (IDMOP), that interface is used to perform the binding.

COM interop binding –

Deep equivalence between the dynamic and object types.

var and dynamic are different, since var is checked on compile time.

Fields, properties, methods, events, constructors, indexers, operators, and conversions can all be called dynamically.

Effect of dynamic type information is cascading:

dynamic x = 2;

var y = x * 3; // Static type of y is dynamic

Dynamic method can be used for method overloading for methods that have statically bound values.

Functions that could not be called dynamically:

– Extension methods (via extension method syntax)

– Members of an interface, if you need to cast to that interface to do so

– Base members hidden by a subclass

Attributes

Attributes are an extensible mechanism for adding custom information to code elements (assemblies, types, members, return values, parameters, and generic type parameters). This extensibility is useful for services that integrate deeply into the type system, without requiring special keywords or constructs in the C# language.

BitArray is a dynamically sized collection of compacted bool values. It is more memory-efficient than both a simple array of bool and a generic List of bool, because it uses only one bit for each value, whereas the bool type otherwise occupies one byte for each value.

HashSet<T> and SortedSet<T>

Peculiarity:

• Their Contains methods execute quickly using a hash-based lookup.

• They do not store duplicate elements and silently ignore requests to add

duplicates.

• You cannot access an element by position.

Dictionaries are collection in which each element is a key/value pair.

In Big-O notation, retrieval time by key is:

• O(1) for Hashtable, Dictionary, and OrderedDictionary

• O(log n) for SortedDictionary and SortedList

• O(n) for ListDictionary (and nondictionary types such as List<T>)

Hashtable (non generic) – is nongeneric Dictionary

OrderedDictionary (non generic) is a nongeneric dictionary that maintains elements in the same order that they were added. With an OrderedDictionary, you can access elements both by index and by key.

ListDictionary (non generic) uses a singly linked list to store the data. Its efficiency with very small lists (fewer than 10 items).

HybridDictionary (non generic) is a ListDictionary (non generic) that automatically converts to a Hashtable upon reaching a certain size.

SortedDictionary<,> (red/black tree based) is much faster than SortedList<,> at inserting elements in a random sequence.

SortedList<,> is implemented internally with an ordered array pair, fast retrieval (via a binary-chop search) but poor insertion performance. It has an extra ability: to access items by index as well as by key.

ReadOnlyCollection<T> is a wrapper, or proxy, that provides a read-only view of a collection.

– A type for which Equals and GetHashCode return meaningful results can be used as a key in a Dictionary or Hashtable.

– A type that implements IComparable /IComparable<T> can be used as a key in any of the sorted dictionaries or lists.

public interface IEqualityComparer<T>

{

bool Equals (T x, T y);

int GetHashCode (T obj);

}

public interface IComparer <in T>

{

int Compare(T x, T y);

}

For structs:

public interface IStructuralEquatable

{

bool Equals (object other, IEqualityComparer comparer);

int GetHashCode (IEqualityComparer comparer);

}

public interface IStructuralComparable

{

int CompareTo (object other, IComparer comparer);

}

LINQ

LINQ enables you to query any collection implementing IEnumerable<T>.

Implemented as extension method on collection

Prototype

public static IEnumerable<TSource> Where<TSource>

(this IEnumerable<TSource> source, Func<TSource,bool> predicate)

public static IEnumerable<TSource> OrderBy<TSource,TKey>

(this IEnumerable<TSource> source, Func<TSource,TKey> keySelector)

public static IEnumerable<TResult> Select<TSource,TResult>

(this IEnumerable<TSource> source, Func<TSource,TResult> selector)

Some lambdas can change the type of each element.

Query expressions always start with a from clause and end with either a select or group clause.

Range variable n appears in every clause in the query. And yet, the variable actually enumerates over a different sequence with each clause.

Deferred execution – means that query is executed when it is enumerated, not when constructed.

Reevaluation – means that query executed each time when it is enumerated.

Capturing variables – variable is captured, but read and used while query execution.

The let Keyword – introduces a new variable alongside the range variable.

IEnumerable<string> query = from n in names

let vowelless = n.Replace (“a”, “”)

where vowelless.Length > 2 orderby vowelless select n;

Interpreted Queries – for remote datasource.

They operate over sequences that implement IQueryable<T>, and they resolve to the query operators in the Queryable class, which emit expression trees that are interpreted at runtime.

There are two IQueryable<T> implementations in the .NET Framework:

– LINQ to SQL

– Entity Framework (EF)

It’s also possible to generate an IQueryable<T> wrapper around an ordinary enumerable

collection by calling the AsQueryable method.

Combining Interpreted and Local Queries

A query can include both interpreted and local operators. A typical pattern is to have the local operators on the outside and the interpreted components on the inside; in other words, the interpreted queries feed the local queries.

Interpreted queries, which use Queryable operators, take expression trees.

We can see this by comparing the signature of the Where operator in Enumerable and Queryable:

Cast – converts IEnumerable to IEnumerable<T>, throwing an exception if there are any wrongly

typed elements

ToArray – converts IEnumerable<T> to T[]

ToList – converts IEnumerable<T> to List<T>

ToDictionary – converts IEnumerable<T> to Dictionary<TKey,TValue>

ToLookup – converts IEnumerable<T> to ILookup<TKey,TElement>

AsEnumerable – downcasts to IEnumerable<T>

AsQueryable – casts or converts to IQueryable<T>

Element Operators IEnumerable<TSource>→ TSource

First, FirstOrDefault – returns the first element in the sequence, optionally satisfying a predicate

Last, LastOrDefault – returns the last element in the sequence, optionally satisfying a predicate

Single, SingleOrDefault – equivalent to First/First OrDefault, but throws an exception if there is more than one match

ElementAt, ElementAtOrDefault – returns the element at the specified position

DefaultIfEmpty – returns a single-element sequence whose value is default(TSource) if the sequence has no elements

Aggregation Methods IEnumerable<TSource>→ scalar

Count, LongCount – returns the number of elements in the input sequence, optionally satisfying a predicate

Min, Max – returns the smallest or largest element in the sequence

Sum, Average – calculates a numeric sum or average over elements in the sequence

Aggregate – performs a custom aggregation

Quantifiers IEnumerable<TSource>→ bool

Contains – returns true if the input sequence contains the given element

Any – returns true if any elements satisfy the given predicate

All – returns true if all elements satisfy the given predicate

SequenceEqual – returns true if the second sequence has identical elements to the input sequence

Generation Methods void→IEnumerable<TResult>

Empty – creates an empty sequence

Repeat – creates a sequence of repeating elements

Range – creates a sequence of integersX-DOM

<customer id=”123″>

<firstname>Joe</firstname>

<lastname>Bloggs<!–nice name–></lastname>

</customer>

XElement lastName = new XElement (“lastname”, “Bloggs”);

lastName.Add (new XComment (“nice name”));

XElement customer = new XElement (“customer”);

customer.Add (new XAttribute (“id”, 123));

customer.Add (new XElement (“firstname”, “Joe”));

customer.Add (lastName);

or

XElement customer =

new XElement (“customer”, new XAttribute (“id”, 123),

new XElement (“firstname”, “joe”),

new XElement (“lastname”, “bloggs”,

new XComment (“nice name”)

)

);

Disposal and Garbage collection

IDisposable interface

public interface IDisposable

{

void Dispose();

}

using statement provides a syntactic shortcut for calling Dispose on objects that implement IDisposable, using a try/finally block. For example:

using (FileStream fs = new FileStream (“myFile.txt”, FileMode.Open))

{

// … Write to the file …

}

The compiler converts this to:

FileStream fs = new FileStream (“myFile.txt”, FileMode.Open);

try

{

// … Write to the file …

}

finally

{

if (fs != null) ((IDisposable)fs).Dispose();

}

Disposal rules:

1. Disposed object could not be called (exception).

2. Dispose() method could not be called twice (exception).

3. Disposed object should call dispose for all its disposable members.

A root is something that keeps an object alive. If an object is not directly or indirectly referenced by a root, it will be eligible for garbage collection.

A root is one of the following:

– A local variable or parameter in an executing method (or in any method in its call stack)

– A static variable

– An object on the queue that stores objects ready for finalization

Finalizers (destructor)

Prior to an object being released from memory, its finalizer runs, if it has one. A finalizer is declared like a constructor, but it is prefixed by the ˜ symbol:

class Test

{

˜Test()

{

// Finalizer logic…

}

}

Finalizer cannot be declared as public or static, cannot have parameters, and cannot call the base class.

Here are some guidelines for implementing finalizers:

– Ensure that your finalizer executes quickly.

– Never block in your finalizer (Chapter 14).

– Don’t reference other finalizable objects.

– Don’t throw exceptions.

Resurrection

Suppose a finalizer modifies a living object such that it refers back to the dying object (someone will refer it while object finalization called). When the next garbage collection happens (for the object’s generation), the CLR will see the previously dying object as no longer orphaned—and so it will evade garbage collection.

A resurrected object’s finalizer will not run a second time – unless you call GC.ReRegisterForFinalize.

GC performance optimization techniques:

1. Generational collection

2. Large object heap (LOH)

3. Background collection for Gen2

4. GC notifications

GC.AddMemoryPressure and GC.RemoveMemoryPressure – tell to CLR about unmanaged memory used to optimize.

Weak References – not tracked by CLR.

var sb = new StringBuilder (“this is a test”);

var weak = new WeakReference (sb);

CODE ORGANISATION

Preprocessor directives – conditional compilation, conditional attributes (some class method can be marked by conditional attribute, and all calls to this method will be skipped in case attribute is not defined)

Debug and Trace Classes – all methods of the Debug class are defined with [Conditional(“DEBUG”)] or [Conditional(“TRACE”)]. Both define methods: Fail (shows dialog) and Assert. There is listener that listen debug and trace events, by default there is only one.

Code contract –

Contract.Requires (list != null); // Precondition

Contract.Ensures (list.Contains (item)); // Postcondition

ccrewrite.exe tool should be invoked with app with contracts, it replace some contract instructions into right place.

Purity

All functions that you call from arguments passed to contract methods (Requires, Assumes, Assert, etc.) must be pure, means they must not alter the values of fields. Purity set be attribute.

[Pure]

public static bool IsValidUri (string uri) { … }

It is possible to specify what exception will be thrown in case contract is broken and and scope of code block that is guarded by contract.

Contracts on Interfaces and Abstract Methods – can attach conditions to interface members and abstract methods. The binary rewriter then automatically weaves these conditions into the members’ concrete implementations.

Debugger Integration

DbgCLR is Visual Studio stripped of everything but the debugger, and it is a free download with the .NET Framework SDK. It requires that you download the whole SDK.

There is static debugger class, it is possible attach, navigate and explore program execution.

Windows Event Logs – it is possible write, read and monitor it.

Performance Counters – it is possible to work with Windows performance counters.

Stopwatch class – for measuring execution times.

Threading

Thread can execute, sleep, join to another thread and wait (on lock for example).

Lock – instruction that allows to guard some block of code only fo one single thread execution (like CS)

lock (<any referenceable object instance>)

{

//only one thread here

}

try-catch for getting thread exception should be located inside a thread that executes, but on in thread which starts it.

In WPF, Metro, and Windows Forms applications, you can subscribe to “global” exception handling events, Application.DispatcherUnhandledException and Application.ThreadException.

Foreground threads – threads created by default, app wait for all foreground threads to be terminated before exiting.

Background threads – are shutted down when application is closed (even finally blocks are not executed).

int result = task.Result; – if task is not finished, this blocks the current thread.

Task Exceptions are passed to waiting thread

It is possible subscribe to unobserved exceptions at a global level via the static event TaskScheduler.UnobservedTaskException. to catch all exception from all threads.

Continuation says to a task, “when you’ve finished, continue by doing something else.” – callback that executes once upon completion of an operation.

var awaiter = task.GetAwaiter();

awaiter.OnCompleted (<lambda here>);

or

task.ContinueWith (<lambda here>);

Lambda can call int result = awaiter.GetResult(); to get result or an exception in case exception happened while task execution.

TaskCompletionSource

Allows you to create a manually driven task

Awaiting

Transformed from

var result = await expression;

statement(s);

Transformed to

var awaiter = expression.GetAwaiter();

awaiter.OnCompleted (() =>

{

var result = awaiter.GetResult();

statement(s);

);

Methods with the async modifier are called asynchronous functions, because they themselves are typically asynchronous.

await expression can appear in place of any expression (within an asynchronous function) except for inside a catch or finally block, lock expression, unsafe context or an executable’s entry point (main method).

Unnamed lambda also can be async.

Exception thrown after await instruction by default is posted besides sync context of current thread and can crush the program (unless it caught by general exception handler).

Optimisation for async:

1. Completing synchrony – we can cache all results within a async function and check that perhaps result is already evaluated and can be returned immediately.

2.

Async patterns

1. Cancellation – cancellation token passed to most async functions and can be configured outside to stop function execution.

2. Progress reporting – callback object is used to provide feedback about progress of task.

3. Task-based Asynchronous Pattern (TAP) – set of obligations for some methods to be true async: return a hot task, have “Async” suffix, accept cancellation and progress tracking objects, return result quickly, do not hold thread in case I/O.

4. Task Combinators – WhenAny (returned first finished task), WhenAll (returned array of results of all tasks), it possible to write own combinators.

– The binary serializer – old for Remouting (except in the Metro profile)

– The (attribute-based) XML serializer – old for SOAP(XmlSerializer)

– The IXmlSerializable interface (implementing own serializer)

Data Contract Serializer types:

– DataContractSerializer (Loosely couples .NET types)

– NetDataContractSerializer (Tightly couples .NET types)

Attributes for markup

namespace SerialTest

{

[DataContract] public class Person

{

[DataMember] public string Name;

[DataMember] public int Age;

}

}

Subclasses and referenced objects are serialized as well.

The NetDataContractSerializer always preserves referential equality. The DataCon tractSerializer does not, unless you specifically ask it to. This means that if the same object is referenced in two different places, a DataCon tractSerializer ordinarily writes it twice.

Version Tolerance

By default missed fields is not a problem, but [DataMember (IsRequired=true)] – makes an exception in case of missed field.

It is possible to specify a hook-delegate the called before/after serialization/deserialization by specifying an attribute on some method: [OnSerializing], [OnSerialized], [OnDeserializing], [OnDeserialized].

The Binary Serializer – for remoting and disk saving, is not available in Metro.

[Serializable] public sealed class Person

{

public string Name;

public int Age;

}

The Serializable attribute is not inherited

With automatic properties, the binary serialization engine serializes the underlying compiler-generated field. The name of this field, unfortunately, can change when its type is recompiled, breaking compatibility with existing serialized data. The workaround is either to avoid automatic properties

Formatters for serialization:BinaryFormatter and SoapFormatter

Binary Serialization Attributes

[NonSerialized] – marks the fields that should ot be serialized (that can be dynamically calculated for instance)

A WinRT library has a .winmd extension and is similar to a .dll, except that it contains only metadata and no IL code.

An assembly contains four kinds of things:

– An assembly manifest (mandatory) – Provides information to the .NET runtime, such as the assembly’s name, version, requested permissions, and other assemblies that it references

– An application manifest – Provides information to the operating system, such as how the assembly should be deployed and whether administrative elevation is required

– Compiled types – The compiled IL code and metadata of the types defined within the assembly

– Resources – Other data embedded within the assembly, such as images and localizable text

The assembly manifest serves two purposes:

• It describes the assembly to the managed hosting environment.

• It acts as a directory to the modules, types, and resources in the assembly.

Multifile assemblies have to be compiled from the command line

The Assembly class in System.Reflection is a gateway to accessing assembly metadata

at runtime

A strongly named assembly has a unique and untamperable identity. It works by adding two bits of metadata to the manifest:

– A unique number that belongs to the authors of the assembly

– A signed hash of the assembly, proving that the unique number holder produced the assembly

A delay-signed assembly is flagged with the correct public key, but not signed with the private key. A delay-signed assembly is equivalent to a tampered assembly and would normally be rejected by the CLR. The developer, however, instructs the CLR to bypass validation for the delay-sign assemblies on that computer, allowing the unsigned assemblies to run. When it comes time for final deployment, the private key holder re-signs the assembly with the real key pair.

Authenticode is a code-signing system whose purpose is to prove the identity of the publisher. Published certificates are used. Authenticode and strong-name signing are independent: you can sign an assembly with either or both systems. It is not only for managed binaries – for native as well.

Global Assembly Cache – for assemblies in the GAC, versioning is centralized at the machine

level and controlled by the computer’s administrator. For assemblies outside the

GAC, versioning is handled on an application basis, so each application looks after

its own dependency and update issues (typically by maintaining its own copy of each

assembly that it references).

GAC disadv:

– admin privileges for installation are required

– GAC modules are prefered over local

– GAC modules are used by multiple app – so the broken binary will affect all of them

Installing assembly at GAC: gacutil /i MyAssembly.dll

Uninstalling assembly at GAC: gacutil /u MyAssembly

Installing a new version of assembly – does not remove the previous one – both are kept by GAC (uninstall+install can be used as workaround).

Resources: for binary data or for something that should be localized.

Resources can be embedded directly or through .resource file

.resource file – for potentially localizable content (it can be explored by specific API). It is binary files are built over .resx human readable files (XML based)

CurrentCulture reflects the regional settings of the Windows control panel, whereas

CurrentUICulture reflects the language of the operating system.

Regional settings – timezone and format of currency and dates.

CurrentCulture determines the default behavior of such functions as DateTime.Parse.

CurrentUICulture determines the language in which the computer communicates with the user.

ResourceManager, by default, uses the current thread’s CurrentUICulture property to determine the correct satellite assembly to load.

Resolving Assemblies

First The CLR checks whether assembly is already loaded from probing path of as AssemblyResolve event result and return it, next – first checks the GAC, then the probing paths (generally the application base directory), and as a final resort, fires the AppDomain.AssemblyResolve event. If none returns a match, the CLR throws an exception.

Loading Assemblies

To load an assembly from a filename, call LoadFrom or LoadFile.

To load an assembly from a URI, call LoadFrom.

To load an assembly from a byte array, call Load.

if an assembly with the same identity has already been loaded into memory from another location, LoadFrom gives you the previous copy, LoadFile gives you a fresh copy.

Load twice from an identical location, however, both methods give you the previously cached copy.

Loading an assembly twice from an identical byte array gives you two distinct Assembly objects.

LoadFrom hints the CLR as to the location of onward references, whereas LoadFile does not.

Statically referenced types – when one assembly reference a type (directly from source code) from another assembly.

Dynamic type reference – when one assembly loads dynamically another and create instance of type through Activator.CreateInstance (or in some other way).

It is called resolution context – in case this approaches are mixed – two different copies of assembly will be loaded.

Whether you use LoadFrom or LoadFile, the CLR always looks first for the requested assembly in the GAC. You can bypass the GAC with ReflectionOnlyLoadFrom (which loads the assembly into a reflection-only context). Even loading from a byte array doesn’t bypass the GAC, although it gets around the problem of locking assembly files:

byte[] image = File.ReadAllBytes (assemblyPath);

Assembly a = Assembly.Load (image);

If loaded from the Internet, where CodeBase is the Internet URI and Location is the temporary path to which it was downloaded. Another special case is with shadow copied assemblies, where Location is blank and CodeBase is its unshadowed location.

Packing a Single-File Executable – it is possible to pack all dependent assemblies as resources into main binary and loads them from there.

Reflection and Metadata

System.Type represents the metadata for a type

Type t1 = DateTime.Now.GetType(); // Type obtained at runtime

Type t2 = typeof (DateTime); // Type obtained at compile time

Nested types can be obtained also.

Dictionary’2 – generic type name with two parameters after apostrophe

Byte* – for pointer types

Boolean& – for ref and out types

It is possible get interface list of interfaces that are inherited by some type.

Instantiating Types – two ways to dynamically instantiate an object from its type:

– Call the static Activator.CreateInstance method

– Call Invoke on a ConstructorInfo object obtained from calling GetConstructor on a Type (advanced scenarios)

It is possible to call methods dynamically – to make it faster it is possible to create a delegate on dynamically got method and call it multiple times.

lock statement is in fact a syntactic shortcut for a call to the methods Monitor.Enter and Monitor.Exit. Monitor.Enter is overloaded with argument that specifies whether their locking was obtained at all. Monitor.TryEnter – allows specifying time span that allowed for getting into locked section, and returns true on success, otherwise – false. With zero timespan – it is possible to test whether at all the monitor can be locked.

Sync object – any referenced type, even local variables captured by lambda expressions or anonymous methods.

lock (typeof (Widget)) { … } – For protecting access to statics

When to lock – any writable shared field

Nested locking and deadlock.

Mutex – crossprocess lock (slower than locking in ~50 times).

WaitOne – to lock, ReleaseMutex – to unlock.

Common pattern throughout the .NET Framework: static members are thread-safe; instance members are not. But it should be code manually.

Immutable objects – with readonly fields.

Non-Exclusive Locking – Semaphore

SemaphoreSlim – for one process only.

Semaphore differs from lock and Mutex at fact that it can be locked and released by different threads.

ReaderWriterLockSlim – has different types of locking for reading and writing – simultaneous reading is allowed, writing is not (recursion supported).

Events – AutoResetEvent, ManualResetEvent(Slim), and CountdownEvent.

CountdownEvent lets you wait on more than one thread. Threads are stopped until event will not be signaled specified amount of times.

ThreadPool.RegisterWaitForSingleObject – it is possible to subscribe for event some delegate.

It is possible to convert event into task.

Wait functions – WaitAny, WaitAll, and SignalAndWait.

The Barrier class implements a thread execution barrier, allowing many threads to rendezvous at a point in time.

AttachedToParent – parent task waits for any child task for completion, exception of child’s task will be aggregated.

Task.WaitAll – if one or more of the tasks throw an unhandled exception, WaitAll still waits out every task—and then re-throws an AggregateException that accumulates the exceptions from each faulted task.

BlockingCollection<T> – blocking collection wraps any collection that implements IProducerConsumerCollection<T> and lets you Take an element from the wrapped collection—blocking if no element is available.

Application Domains

AppDomain newDomain = AppDomain.CreateDomain (“New Domain”);

newDomain.ExecuteAssembly (“test.exe”);

AppDomain.Unload (newDomain);

DoCallBack – executes on another application domain, a method on a given type