Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .openpublishing.redirection.json
Original file line number Diff line number Diff line change
Expand Up @@ -1514,6 +1514,14 @@
"source_path":"docs/csharp/programming-guide/concepts/threading/thread-synchronization.md",
"redirect_url":"/dotnet/standard/threading/overview-of-synchronization-primitives"
},
{
"source_path":"docs/csharp/programming-guide/concepts/threading/index.md",
"redirect_url":"/dotnet/standard/threading/"
},
{
"source_path":"docs/visual-basic/programming-guide/concepts/threading/index.md",
"redirect_url":"/dotnet/standard/threading/"
},
{
"source_path":"docs/framework/windows-workflow-foundation/samples/absolute-delay.md",
"redirect_url":"/previous-versions/dotnet/netframework-4.0/ff522352(v%3dvs.100)"
Expand Down
4 changes: 2 additions & 2 deletions docs/csharp/language-reference/keywords/volatile.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ The `volatile` keyword can be applied to fields of these types:

Other types, including `double` and `long`, cannot be marked `volatile` because reads and writes to fields of those types cannot be guaranteed to be atomic. To protect multi-threaded access to those types of fields, use the <xref:System.Threading.Interlocked> class members or protect access using the [`lock`](lock-statement.md) statement.

The volatile keyword can only be applied to fields of a `class` or `struct`. Local variables cannot be declared `volatile`.
The `volatile` keyword can only be applied to fields of a `class` or `struct`. Local variables cannot be declared `volatile`.

## Example

The following example shows how to declare a public field variable as `volatile`.

[!code-csharp[declareVolatile](~/samples/snippets/csharp/language-reference/keywords/volatile/Program.cs#Declaration)]

The following example demonstrates how an auxiliary or worker thread can be created and used to perform processing in parallel with that of the primary thread. For background information about multithreading, see [Managed Threading](../../../standard/threading/index.md) and [Threading (C#)](../../programming-guide/concepts/threading/index.md).
The following example demonstrates how an auxiliary or worker thread can be created and used to perform processing in parallel with that of the primary thread. For more information about multithreading, see [Managed Threading](../../../standard/threading/index.md).

[!code-csharp[declareVolatile](~/samples/snippets/csharp/language-reference/keywords/volatile/Program.cs#Volatile)]

Expand Down
1 change: 0 additions & 1 deletion docs/csharp/programming-guide/concepts/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ This section explains programming concepts in the C# language.
|[Object-Oriented Programming (C#)](../../../csharp/programming-guide/concepts/object-oriented-programming.md)|Describes common object-oriented concepts, including encapsulation, inheritance, and polymorphism.|
|[Reflection (C#)](../../../csharp/programming-guide/concepts/reflection.md)|Explains how to use reflection to dynamically create an instance of a type, bind the type to an existing object, or get the type from an existing object and invoke its methods or access its fields and properties.|
|[Serialization (C#)](../../../csharp/programming-guide/concepts/serialization/index.md)|Describes key concepts in binary, XML, and SOAP serialization.|
|[Threading (C#)](../../../csharp/programming-guide/concepts/threading/index.md)|Provides an overview of the .NET threading model and shows how to write code that performs multiple tasks at the same time to improve the performance and responsiveness of your applications.|

## Related Sections

Expand Down
34 changes: 0 additions & 34 deletions docs/csharp/programming-guide/concepts/threading/index.md

This file was deleted.

1 change: 0 additions & 1 deletion docs/csharp/programming-guide/concepts/toc.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,3 @@
## [Object-Oriented Programming](object-oriented-programming.md)
## [Reflection](reflection.md)
## [Serialization (C#)](serialization/)
## [Threading](threading/index.md)
2 changes: 1 addition & 1 deletion docs/standard/threading/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Whether you are developing for computers with one processor or several, you want
Explains how to create, start, pause, resume, and abort threads.

[Managed Threading Best Practices](../../../docs/standard/threading/managed-threading-best-practices.md)
Discusses levels of synchronization, how to avoid deadlocks and race conditions, single-processor and multiprocessor computers, and other threading issues.
Discusses levels of synchronization, how to avoid deadlocks and race conditions, and other threading issues.

[Threading Objects and Features](../../../docs/standard/threading/threading-objects-and-features.md)
Describes the managed classes you can use to synchronize the activities of threads and the data of objects accessed on different threads, and provides an overview of thread pool threads.
Expand Down
49 changes: 15 additions & 34 deletions docs/standard/threading/managed-threading-best-practices.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Managed Threading Best Practices"
ms.date: "11/30/2017"
ms.date: "10/15/2018"
ms.technology: dotnet-standard
dev_langs:
- "csharp"
Expand All @@ -13,13 +13,13 @@ ms.assetid: e51988e7-7f4b-4646-a06d-1416cee8d557
author: "rpetrusha"
ms.author: "ronpet"
---
# Managed Threading Best Practices
# Managed threading best practices
Multithreading requires careful programming. For most tasks, you can reduce complexity by queuing requests for execution by thread pool threads. This topic addresses more difficult situations, such as coordinating the work of multiple threads, or handling threads that block.

> [!NOTE]
> Starting with the .NET Framework 4, the Task Parallel Library and PLINQ provide APIs that reduce some of the complexity and risks of multi-threaded programming. For more information, see [Parallel Programming in .NET](../../../docs/standard/parallel-programming/index.md).

## Deadlocks and Race Conditions
## Deadlocks and race conditions
Multithreading solves problems with throughput and responsiveness, but in doing so it introduces new problems: deadlocks and race conditions.

### Deadlocks
Expand Down Expand Up @@ -53,7 +53,7 @@ else {
}
```

### Race Conditions
### Race conditions
A race condition is a bug that occurs when the outcome of a program depends on which of two or more threads reaches a particular block of code first. Running the program many times produces different results, and the result of any given run cannot be predicted.

A simple example of a race condition is incrementing a field. Suppose a class has a private **static** field (**Shared** in Visual Basic) that is incremented every time an instance of the class is created, using code such as `objCt++;` (C#) or `objCt += 1` (Visual Basic). This operation requires loading the value from `objCt` into a register, incrementing the value, and storing it in `objCt`.
Expand All @@ -64,39 +64,20 @@ else {

Race conditions can also occur when you synchronize the activities of multiple threads. Whenever you write a line of code, you must consider what might happen if a thread were preempted before executing the line (or before any of the individual machine instructions that make up the line), and another thread overtook it.

## Number of Processors
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this content is much less important than it once was, but it still can be important. It's worth adding a short Number of processors section after the Static members section that says something like, "Whether there are multiple processors or only one processor available on a system can influence multithreaded architecture. For more information, see [Number of Processors](https://docs.microsoft.com/en-us/previous-versions/dotnet/netframework-1.1/1c9txz50(v%3dvs.71)#number-of-processors). You can determine the number of processors available at runtime by retrieving the value of the <xref:System.Environment.ProcessorCount?displayProperty=nameWithType> property.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The link to the ProcessorCount property is a good addition. Thanks!

Most computers now have multiple processors (also called cores), even small devices such as tablets and phones. If you know you're developing software that will also run on single-processor computers, you should be aware that multithreading solves different problems for single-processor computers and multiprocessor computers.

### Multiprocessor Computers
Multithreading provides greater throughput. Ten processors can do ten times the work of one, but only if the work is divided so that all ten can be working at once; threads provide an easy way to divide the work and exploit the extra processing power. If you use multithreading on a multiprocessor computer:

- The number of threads that can execute concurrently is limited by the number of processors.

- A background thread executes only when the number of foreground threads executing is smaller than the number of processors.

- When you call the <xref:System.Threading.Thread.Start%2A?displayProperty=nameWithType> method on a thread, that thread might or might not start executing immediately, depending on the number of processors and the number of threads currently waiting to execute.

- Race conditions can occur not only because threads are preempted unexpectedly, but because two threads executing on different processors might be racing to reach the same code block.

### Single-Processor Computers
Multithreading provides greater responsiveness to the computer user, and uses idle time for background tasks. If you use multithreading on a single-processor computer:

- Only one thread runs at any instant.

- A background thread executes only when the main user thread is idle. A foreground thread that executes constantly starves background threads of processor time.

- When you call the <xref:System.Threading.Thread.Start%2A?displayProperty=nameWithType> method on a thread, that thread does not start executing until the current thread yields or is preempted by the operating system.

- Race conditions typically occur because the programmer did not anticipate the fact that a thread can be preempted at an awkward moment, sometimes allowing another thread to reach a code block first.

## Static Members and Static Constructors
## Static members and static constructors
A class is not initialized until its class constructor (`static` constructor in C#, `Shared Sub New` in Visual Basic) has finished running. To prevent the execution of code on a type that is not initialized, the common language runtime blocks all calls from other threads to `static` members of the class (`Shared` members in Visual Basic) until the class constructor has finished running.

For example, if a class constructor starts a new thread, and the thread procedure calls a `static` member of the class, the new thread blocks until the class constructor completes.

This applies to any type that can have a `static` constructor.

## Number of processors

Whether there are multiple processors or only one processor available on a system can influence multithreaded architecture. For more information, see [Number of Processors](https://docs.microsoft.com/previous-versions/dotnet/netframework-1.1/1c9txz50(v%3dvs.71)#number-of-processors).

Use the <xref:System.Environment.ProcessorCount?displayProperty=nameWithType> property to determine the number of processors available at runtime.

## General Recommendations
## General recommendations
Consider the following guidelines when using multiple threads:

- Don't use <xref:System.Threading.Thread.Abort%2A?displayProperty=nameWithType> to terminate other threads. Calling **Abort** on another thread is akin to throwing an exception on that thread, without knowing what point that thread has reached in its processing.
Expand Down Expand Up @@ -139,7 +120,7 @@ else {
```

> [!NOTE]
> In the .NET Framework version 2.0, the <xref:System.Threading.Interlocked.Add%2A> method provides atomic updates in increments larger than 1.
> In the .NET Framework 2.0 and later, use the <xref:System.Threading.Interlocked.Add%2A> method for atomic increments larger than 1.

In the second example, a reference type variable is updated only if it is a null reference (`Nothing` in Visual Basic).

Expand Down Expand Up @@ -177,9 +158,9 @@ else {
```

> [!NOTE]
> In the .NET Framework version 2.0, the <xref:System.Threading.Interlocked.CompareExchange%2A> method has a generic overload that can be used for type-safe replacement of any reference type.
> Beginning with .NET Framework 2.0, the <xref:System.Threading.Interlocked.CompareExchange%60%601%28%60%600%40%2C%60%600%29> method overload provides a type-safe alternative for reference types.

## Recommendations for Class Libraries
## Recommendations for class libraries
Consider the following guidelines when designing class libraries for multithreading:

- Avoid the need for synchronization, if possible. This is especially true for heavily used code. For example, an algorithm might be adjusted to tolerate a race condition rather than eliminate it. Unnecessary synchronization decreases performance and creates the possibility of deadlocks and race conditions.
Expand Down
Loading