diff --git a/xml/System.Threading/Thread.xml b/xml/System.Threading/Thread.xml index 58954d2042d..a282f90b5ff 100644 --- a/xml/System.Threading/Thread.xml +++ b/xml/System.Threading/Thread.xml @@ -94,7 +94,7 @@ The constructors can take either of two delegate types, depending on whether you can pass an argument to the method to be executed: -- If the method has no arguments, you pass a delegate to the constructor. It has the signature: +- If the method has no arguments, you pass a delegate to the constructor. It has the signature: ```csharp public delegate void ThreadStart() @@ -104,12 +104,12 @@ Public Delegate Sub ThreadStart() ``` - The following example creates and starts a thread that executes the `ExecuteInForeground` method. The method displays information about some thread properties, then executes a loop in which it pauses for half a second and displays the elapsed number of seconds. When the thread has executed for at least five seconds, the loop ends and the thread terminates execution. + The following example creates and starts a thread that executes the `ExecuteInForeground` method. The method displays information about some thread properties, then executes a loop in which it pauses for half a second and displays the elapsed number of seconds. When the thread has executed for at least five seconds, the loop ends and the thread terminates execution. :::code language="csharp" source="~/snippets/csharp/System.Threading/Thread/Overview/ThreadStart1.cs" id="Snippet1"::: :::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/System.Threading.Thread/vb/ThreadStart1.vb" id="Snippet1"::: -- If the method has an argument, you pass a delegate to the constructor. It has the signature: +- If the method has an argument, you pass a delegate to the constructor. It has the signature: ```csharp public delegate void ParameterizedThreadStart(object obj) @@ -126,11 +126,11 @@ :::code language="csharp" source="~/snippets/csharp/System.Threading/Thread/Overview/ThreadStart2.cs" id="Snippet2"::: :::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/System.Threading.Thread/vb/ThreadStart2.vb" id="Snippet2"::: - It is not necessary to retain a reference to a object once you have started the thread. The thread continues to execute until the thread procedure is complete. + It isn't necessary to retain a reference to a object once you've started the thread. The thread continues to execute until the thread procedure is complete. ## Retrieving Thread objects - You can use the static (`Shared` in Visual Basic) property to retrieve a reference to the currently executing thread from the code that the thread is executing. The following example uses the property to display information about the main application thread, another foreground thread, a background thread, and a thread pool thread. + You can use the static (`Shared` in Visual Basic) property to retrieve a reference to the currently executing thread from the code that the thread is executing. The following example uses the property to display information about the main application thread, another foreground thread, a background thread, and a thread pool thread. :::code language="csharp" source="~/snippets/csharp/System.Threading/Thread/Overview/Instance1.cs" id="Snippet4"::: :::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/System.Threading.Thread/vb/Instance1.vb" id="Snippet4"::: @@ -141,29 +141,29 @@ By default, the following threads execute in the foreground: -- The main application thread. +- The main application thread. -- All threads created by calling a class constructor. +- All threads created by calling a class constructor. The following threads execute in the background by default: -- Thread pool threads, which are a pool of worker threads maintained by the runtime. You can configure the thread pool and schedule work on thread pool threads by using the class. +- Thread pool threads, which come from a pool of worker threads maintained by the runtime. You can configure the thread pool and schedule work on thread pool threads by using the class. > [!NOTE] > Task-based asynchronous operations automatically execute on thread pool threads. Task-based asynchronous operations use the and classes to implement the [task-based asynchronous pattern](/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap). -- All threads that enter the managed execution environment from unmanaged code. +- All threads that enter the managed execution environment from unmanaged code. - You can change a thread to execute in the background by setting the property at any time. Background threads are useful for any operation that should continue as long as an application is running but should not prevent the application from terminating, such as monitoring file system changes or incoming socket connections. + You can change a thread to execute in the background by setting the property at any time. Background threads are useful for any operation that should continue as long as an application is running but should not prevent the application from terminating, such as monitoring file system changes or incoming socket connections. - The following example illustrates the difference between foreground and background threads. It is like the first example in the [Starting a thread](#Starting) section, except that it sets the thread to execute in the background before starting it. As the output shows, the loop is interrupted before it executes for five seconds. + The following example illustrates the difference between foreground and background threads. It's like the first example in the [Starting a thread](#Starting) section, except that it sets the thread to execute in the background before starting it. As the output shows, the loop is interrupted before it executes for five seconds. :::code language="csharp" source="~/snippets/csharp/System.Threading/Thread/Overview/BackgroundEx1.cs" id="Snippet3"::: :::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/System.Threading.Thread/vb/BackgroundEx1.vb" id="Snippet3"::: ## Culture and threads - Each thread has a culture, represented by the property, and a UI culture, represented by the property. The current culture supports such culture-sensitive operations as parsing and formatting, string comparison and sorting, and also controls the writing system and calendar used by a thread. The current UI culture provides for culture-sensitive retrieval of resources in resource files. + Each thread has a culture, represented by the property, and a UI culture, represented by the property. The current culture supports culture-sensitive operations, such as parsing and formatting, string comparison, and sorting, and also controls the writing system and calendar used by a thread. The current UI culture provides for culture-sensitive retrieval of resources in resource files. > [!IMPORTANT] > The and properties don't work reliably when used with any thread other than the current thread. In .NET Framework, reading these properties is reliable, although setting these properties for a thread other than the current thread is not. On .NET Core, an is thrown if a thread attempts to read or write these properties on a different thread. @@ -172,36 +172,36 @@ When a new thread is instantiated, its culture and UI culture are defined by the current system culture and UI culture, and not by the culture and UI culture of the thread from which the new thread is created. This means, for example, that if the current system culture is English (United States) and the current culture of the primary application thread is French (France), the culture of a new thread created by calling the constructor from the primary thread is English (United States), and not French (France). For more information, see the "Culture and threads" section of the class topic. > [!IMPORTANT] -> This is not true of threads that execute asynchronous operations for apps that target the .NET Framework 4.6 and later versions, In this case, the culture and UI culture is part of an asynchronous operations' context; the thread on which an asynchronous operation executes by default inherits the culture and UI culture of the thread from which the asynchronous operation was launched. For more information, see the "Culture and task-based asynchronous operations" section of the class topic. +> This is not true of threads that execute asynchronous operations for apps that target .NET Framework 4.6 and later versions. In this case, the culture and UI culture is part of an asynchronous operation's context; the thread on which an asynchronous operation executes by default inherits the culture and UI culture of the thread from which the asynchronous operation was launched. For more information, see the "Culture and task-based asynchronous operations" section of the class remarks. You can do either of the following to ensure that all of the threads executing in an application share the same culture and UI culture: -- You can pass a object that represents that culture to the delegate or the method. +- You can pass a object that represents that culture to the delegate or the method. -- For apps running on the .NET Framework 4.5 and later versions, you can define the culture and UI culture that is to be assigned to all threads created in an application domain by setting the value of the and properties. Note that this is a per-application domain setting. +- For apps running on .NET Framework 4.5 and later versions, you can define the culture and UI culture that is to be assigned to all threads created in an application domain by setting the value of the and properties. Note that this is a per-application domain setting. - For more information and examples, see the "Culture and threads" section of the class topic. + For more information and examples, see the "Culture and threads" section of the class remarks. ## Getting information about and controlling threads You can retrieve a number of property values that provide information about a thread. In some cases, you can also set these property values to control the operation of the thread. These thread properties include: -- A name. is a write-once property that you can use to identify a thread. Its default value is `null`. +- A name. is a write-once property that you can use to identify a thread. Its default value is `null`. -- A hash code, which you can retrieve by calling the method. The hash code can be used to uniquely identify a thread; for the lifetime of your thread, its hash code will not collide with the value from any other thread, regardless of the application domain from which you obtain the value. +- A hash code, which you can retrieve by calling the method. The hash code can be used to uniquely identify a thread; for the lifetime of your thread, its hash code will not collide with the value from any other thread, regardless of the application domain from which you obtain the value. -- A thread ID. The value of the read-only property is assigned by the runtime and uniquely identifies a thread within its process. +- A thread ID. The value of the read-only property is assigned by the runtime and uniquely identifies a thread within its process. > [!NOTE] > An operating-system [ThreadId](/windows/win32/api/processthreadsapi/nf-processthreadsapi-getthreadid) has no fixed relationship to a managed thread, because an unmanaged host can control the relationship between managed and unmanaged threads. Specifically, a sophisticated host can use the [CLR Hosting API](/dotnet/framework/unmanaged-api/hosting/) to schedule many managed threads against the same operating system thread, or to move a managed thread between different operating system threads. -- The thread's current state. For the duration of its existence, a thread is always in one or more of the states defined by the property. +- The thread's current state. For the duration of its existence, a thread is always in one or more of the states defined by the property. -- A scheduling priority level, which is defined by the property. Although you can set this value to request a thread's priority, it is not guaranteed to be honored by the operating system. +- A scheduling priority level, which is defined by the property. Although you can set this value to request a thread's priority, it is not guaranteed to be honored by the operating system. -- The read-only property, which indicates whether a thread is a thread pool thread. +- The read-only property, which indicates whether a thread is a thread-pool thread. -- The property. For more information, see the [Foreground and background threads](#Foreground) section. +- The property. For more information, see the [Foreground and background threads](#Foreground) section. ## Examples The following example demonstrates simple threading functionality. @@ -299,7 +299,7 @@ Main thread: ThreadProc.Join has returned. Press Enter to end program. A thread does not begin executing when it is created. To schedule the thread for execution, call the method. To pass a data object to the thread, use the method overload. > [!NOTE] -> Visual Basic users can omit the constructor when creating a thread. Use the `AddressOf` operator when passing your method, for example `Dim t As New Thread(AddressOf ThreadProc)`. Visual Basic automatically calls the constructor. +> Visual Basic users can omit the constructor when creating a thread. Use the `AddressOf` operator when passing your method, for example, `Dim t As New Thread(AddressOf ThreadProc)`. Visual Basic automatically calls the constructor. ## Examples The following example shows the syntax for creating and using a delegate with a static method and an instance method. @@ -367,7 +367,7 @@ Main thread: ThreadProc.Join has returned. Press Enter to end program. A thread does not begin executing when it is created. To schedule the thread for execution, call the method. > [!NOTE] -> Visual Basic users can omit the constructor when creating a thread. Use the `AddressOf` operator when passing your method for example `Dim t As New Thread(AddressOf ThreadProc)`. Visual Basic automatically calls the constructor. +> Visual Basic users can omit the constructor when creating a thread. Use the `AddressOf` operator when passing your method, for example, `Dim t As New Thread(AddressOf ThreadProc)`. Visual Basic automatically calls the constructor. ## Examples The following code example shows how to create a thread that executes a static method. @@ -451,7 +451,7 @@ Main thread: ThreadProc.Join has returned. Press Enter to end program. > [!NOTE] > On versions of Microsoft Windows prior to Windows XP and Windows Server 2003, `maxStackSize` is ignored, and the stack size specified in the executable header is used. - If you specify a very small stack size, you might need to disable stack-overflow probing. When the stack is severely constrained, the probing can itself cause a stack overflow. To disable stack overflow probing, add the following to your application configuration file. + If you specify a very small stack size, you might need to disable stack-overflow probing. When the stack is severely constrained, the probing can itself cause a stack overflow. To disable stack overflow probing, add the following to your application configuration file in a .NET Framework app. ```xml @@ -530,7 +530,7 @@ Main thread: ThreadProc.Join has returned. Press Enter to end program. > [!NOTE] > On versions of Microsoft Windows prior to Windows XP and Windows Server 2003, `maxStackSize` is ignored, and the stack size specified in the executable header is used. - If you specify a very small stack size, you might need to disable stack-overflow probing. When the stack is severely constrained, the probing can itself cause a stack overflow. To disable stack overflow probing, add the following to your application configuration file. + If you specify a very small stack size, you might need to disable stack-overflow probing. When the stack is severely constrained, the probing can itself cause a stack overflow. To disable stack overflow probing, add the following to your application configuration file in a .NET Framework app. ```xml @@ -555,14 +555,14 @@ Main thread: ThreadProc.Join has returned. Press Enter to end program. 4.0.0.0 - Raises a in the thread on which it is invoked, to begin the process of terminating the thread. Calling this method usually terminates the thread. + Raises a in the thread on which it's invoked, to begin the process of terminating the thread. Calling this method usually terminates the thread. [!IMPORTANT] -> The `Thread.Abort` method should be used with caution. Particularly when you call it to abort a thread other than the current thread, you don't know what code has executed or failed to execute when the is thrown. You also cannot be certain of the state of your application or any application and user state that it's responsible for preserving. For example, calling `Thread.Abort` may prevent the execution of static constructors or the release of unmanaged resources. +> Use the `Thread.Abort` method with caution. Particularly when you call it to abort a thread other than the current thread, you don't know what code has executed or failed to execute when the is thrown. You also cannot be certain of the state of your application or any application and user state that it's responsible for preserving. For example, calling `Thread.Abort` may prevent the execution of static constructors or the release of managed or unmanaged resources. ]]> @@ -623,7 +623,7 @@ This method is obsolete. On .NET 5 and later versions, calling this method produ When this method is invoked on a thread, the system throws a in the thread to abort it. `ThreadAbortException` is a special exception that can be caught by application code, but is re-thrown at the end of the `catch` block unless is called. `ResetAbort` cancels the request to abort, and prevents the `ThreadAbortException` from terminating the thread. Unexecuted `finally` blocks are executed before the thread is aborted. > [!NOTE] -> When a thread calls `Abort` on itself, the effect is similar to throwing an exception; the happens immediately, and the result is predictable. However, if one thread calls `Abort` on another thread, the abort interrupts whatever code is running. There is also a chance that a static constructor could be aborted. In rare cases, this might prevent instances of that class from being created in that application domain. In the .NET Framework versions 1.0 and 1.1, there is a chance the thread could abort while a `finally` block is running, in which case the `finally` block is aborted. +> When a thread calls `Abort` on itself, the effect is similar to throwing an exception; the happens immediately, and the result is predictable. However, if one thread calls `Abort` on another thread, the abort interrupts whatever code is running. There is also a chance that a static constructor could be aborted. In rare cases, this might prevent instances of that class from being created in that application domain. The thread is not guaranteed to abort immediately, or at all. This situation can occur if a thread does an unbounded amount of computation in the `finally` blocks that are called as part of the abort procedure, thereby indefinitely delaying the abort. To wait until a thread has aborted, you can call the method on the thread after calling the method, but there is no guarantee the wait will end. @@ -712,7 +712,7 @@ This method is obsolete. On .NET 5 and later versions, calling this method produ When this method is invoked on a thread, the system throws a in the thread to abort it. `ThreadAbortException` is a special exception that can be caught by application code, but is re-thrown at the end of the `catch` block unless is called. `ResetAbort` cancels the request to abort, and prevents the `ThreadAbortException` from terminating the thread. Unexecuted `finally` blocks are executed before the thread is aborted. > [!NOTE] -> When a thread calls `Abort` on itself, the effect is similar to throwing an exception; the happens immediately, and the result is predictable. However, if one thread calls `Abort` on another thread, the abort interrupts whatever code is running. There is a chance that a static constructor could be aborted. In rare cases, this might prevent instances of that class from being created in that application domain. In the .NET Framework versions 1.0 and 1.1, there is a chance the thread could abort while a `finally` block is running, in which case the `finally` block is aborted. +> When a thread calls `Abort` on itself, the effect is similar to throwing an exception; the happens immediately, and the result is predictable. However, if one thread calls `Abort` on another thread, the abort interrupts whatever code is running. There is a chance that a static constructor could be aborted. In rare cases, this might prevent instances of that class from being created in that application domain. The thread is not guaranteed to abort immediately, or at all. This situation can occur if a thread does an unbounded amount of computation in the `finally` blocks that are called as part of the abort procedure, thereby indefinitely delaying the abort. To wait until a thread has aborted, you can call the method on the thread after calling the method, but there is no guarantee that the wait will end. diff --git a/xml/System.Threading/ThreadAbortException.xml b/xml/System.Threading/ThreadAbortException.xml index 95cd55aa23a..ebe1f6b3b0c 100644 --- a/xml/System.Threading/ThreadAbortException.xml +++ b/xml/System.Threading/ThreadAbortException.xml @@ -52,19 +52,18 @@ method to destroy a thread, the common language runtime throws a . is a special exception that can be caught, but it will automatically be raised again at the end of the `catch` block. When this exception is raised, the runtime executes all the `finally` blocks before ending the thread. Because the thread can do an unbounded computation in the `finally` blocks or call to cancel the abort, there is no guarantee that the thread will ever end. If you want to wait until the aborted thread has ended, you can call the method. is a blocking call that does not return until the thread actually stops executing. + When a call is made to the method to destroy a thread, the common language runtime throws a on .NET Framework. is a special exception that can be caught, but it will automatically be raised again at the end of the `catch` block. When this exception is raised, the runtime executes all the `finally` blocks before ending the thread. Because the thread can do an unbounded computation in the `finally` blocks or call to cancel the abort, there is no guarantee that the thread will ever end. If you want to wait until the aborted thread has ended, you can call the method. is a blocking call that does not return until the thread actually stops executing. -**.NET Core only:** Even though this type exists in .NET Core, since is not supported, the common language runtime won't ever throw . +> [!NOTE] +> **.NET Core and .NET 5+ only:** Even though this type exists in .NET Core and .NET 5+, since is not supported, the common language runtime won't ever throw . > [!NOTE] -> When the common language runtime (CLR) stops background threads after all foreground threads in a managed executable have ended, it does not use . Therefore, you cannot use to detect when background threads are being terminated by the CLR. +> When the common language runtime (CLR) stops background threads after all foreground threads in a managed executable have ended, it does not use . Therefore, you cannot use to detect when background threads are being terminated by the CLR. - uses the HRESULT COR_E_THREADABORTED, which has the value 0x80131530. + uses `HRESULT COR_E_THREADABORTED`, which has the value `0x80131530`. > [!NOTE] -> The value of the inherited property is always `null`. - - +> The value of the inherited property is always `null`. ## Examples The following example demonstrates aborting a thread. The thread that receives the `ThreadAbortException` uses the method to cancel the abort request and continue executing.