Thread Klass
Definition
Viktigt
En del information gäller för förhandsversionen av en produkt och kan komma att ändras avsevärt innan produkten blir allmänt tillgänglig. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, avseende informationen som visas här.
Skapar och styr en tråd, anger dess prioritet och hämtar dess status.
public ref class Thread sealed : System::Runtime::ConstrainedExecution::CriticalFinalizerObject
public ref class Thread sealed
public ref class Thread sealed : System::Runtime::InteropServices::_Thread
public ref class Thread sealed : System::Runtime::ConstrainedExecution::CriticalFinalizerObject, System::Runtime::InteropServices::_Thread
public sealed class Thread : System.Runtime.ConstrainedExecution.CriticalFinalizerObject
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class Thread
[System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)]
public sealed class Thread : System.Runtime.InteropServices._Thread
[System.Runtime.InteropServices.ComVisible(true)]
[System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)]
public sealed class Thread : System.Runtime.ConstrainedExecution.CriticalFinalizerObject, System.Runtime.InteropServices._Thread
type Thread = class
inherit CriticalFinalizerObject
[<System.Runtime.InteropServices.ComVisible(true)>]
type Thread = class
[<System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)>]
type Thread = class
interface _Thread
[<System.Runtime.InteropServices.ComVisible(true)>]
[<System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)>]
type Thread = class
inherit CriticalFinalizerObject
interface _Thread
Public NotInheritable Class Thread
Inherits CriticalFinalizerObject
Public NotInheritable Class Thread
Public NotInheritable Class Thread
Implements _Thread
Public NotInheritable Class Thread
Inherits CriticalFinalizerObject
Implements _Thread
- Arv
- Arv
-
Thread
- Attribut
- Implementeringar
Exempel
I följande exempel visas enkla trådfunktioner.
using System;
using System.Threading;
// Simple threading scenario: Start a static method running
// on a second thread.
public class ThreadExample {
// The ThreadProc method is called when the thread starts.
// It loops ten times, writing to the console and yielding
// the rest of its time slice each time, and then ends.
public static void ThreadProc() {
for (int i = 0; i < 10; i++) {
Console.WriteLine("ThreadProc: {0}", i);
// Yield the rest of the time slice.
Thread.Sleep(0);
}
}
public static void Main() {
Console.WriteLine("Main thread: Start a second thread.");
// The constructor for the Thread class requires a ThreadStart
// delegate that represents the method to be executed on the
// thread. C# simplifies the creation of this delegate.
Thread t = new Thread(new ThreadStart(ThreadProc));
// Start ThreadProc. Note that on a uniprocessor, the new
// thread does not get any processor time until the main thread
// is preempted or yields. Uncomment the Thread.Sleep that
// follows t.Start() to see the difference.
t.Start();
//Thread.Sleep(0);
for (int i = 0; i < 4; i++) {
Console.WriteLine("Main thread: Do some work.");
Thread.Sleep(0);
}
Console.WriteLine("Main thread: Call Join(), to wait until ThreadProc ends.");
t.Join();
Console.WriteLine("Main thread: ThreadProc.Join has returned. Press Enter to end program.");
Console.ReadLine();
}
}
open System.Threading
// Simple threading scenario: Start a static method running
// on a second thread.
// The ThreadProc method is called when the thread starts.
// It loops ten times, writing to the console and yielding
// the rest of its time slice each time, and then ends.
let threadProc () =
for i = 0 to 9 do
printfn $"ThreadProc: {i}"
// Yield the rest of the time slice.
Thread.Sleep 0
printfn "Main thread: Start a second thread."
// The constructor for the Thread class requires a ThreadStart
// delegate that represents the method to be executed on the
// thread. F# simplifies the creation of this delegate.
let t = Thread threadProc
// Start ThreadProc. Note that on a uniprocessor, the new
// thread does not get any processor time until the main thread
// is preempted or yields. Uncomment the Thread.Sleep that
// follows t.Start() to see the difference.
t.Start()
//Thread.Sleep 0
for _ = 0 to 3 do
printfn "Main thread: Do some work."
Thread.Sleep 0
printfn "Main thread: Call Join(), to wait until ThreadProc ends."
t.Join()
printfn "Main thread: ThreadProc.Join has returned. Press Enter to end program."
stdin.ReadLine() |> ignore
Imports System.Threading
' Simple threading scenario: Start a Shared method running
' on a second thread.
Public Class ThreadExample
' The ThreadProc method is called when the thread starts.
' It loops ten times, writing to the console and yielding
' the rest of its time slice each time, and then ends.
Public Shared Sub ThreadProc()
Dim i As Integer
For i = 0 To 9
Console.WriteLine("ThreadProc: {0}", i)
' Yield the rest of the time slice.
Thread.Sleep(0)
Next
End Sub
Public Shared Sub Main()
Console.WriteLine("Main thread: Start a second thread.")
' The constructor for the Thread class requires a ThreadStart
' delegate. The Visual Basic AddressOf operator creates this
' delegate for you.
Dim t As New Thread(AddressOf ThreadProc)
' Start ThreadProc. Note that on a uniprocessor, the new
' thread does not get any processor time until the main thread
' is preempted or yields. Uncomment the Thread.Sleep that
' follows t.Start() to see the difference.
t.Start()
'Thread.Sleep(0)
Dim i As Integer
For i = 1 To 4
Console.WriteLine("Main thread: Do some work.")
Thread.Sleep(0)
Next
Console.WriteLine("Main thread: Call Join(), to wait until ThreadProc ends.")
t.Join()
Console.WriteLine("Main thread: ThreadProc.Join has returned. Press Enter to end program.")
Console.ReadLine()
End Sub
End Class
Den här koden genererar utdata som liknar följande:
[VB, C++, C#]
Main thread: Start a second thread.
Main thread: Do some work.
ThreadProc: 0
Main thread: Do some work.
ThreadProc: 1
Main thread: Do some work.
ThreadProc: 2
Main thread: Do some work.
ThreadProc: 3
Main thread: Call Join(), to wait until ThreadProc ends.
ThreadProc: 4
ThreadProc: 5
ThreadProc: 6
ThreadProc: 7
ThreadProc: 8
ThreadProc: 9
Main thread: ThreadProc.Join has returned. Press Enter to end program.
Kommentarer
Klassen Thread skapar och styr en tråd, anger dess prioritet och hämtar dess status.
När en process startar skapar den gemensamma språkkörningen automatiskt en enda förgrundstråd för att köra programkod. Tillsammans med den här huvudsakliga förgrundstråden kan en process skapa en eller flera trådar för att köra en del av programkoden som är associerad med processen. Dessa trådar kan köras antingen i förgrunden eller i bakgrunden. Dessutom kan du använda ThreadPool klassen för att köra kod på arbetstrådar som hanteras av den vanliga språkkörningen.
Starta en tråd
Du startar en tråd genom att ange ett ombud som representerar den metod som tråden ska köra i dess klasskonstruktor. Sedan anropar du Start metoden för att påbörja körningen.
Konstruktorerna Thread kan ta någon av två ombudstyper, beroende på om du kan skicka ett argument till den metod som ska köras:
Om metoden inte har några argument skickar du ett ThreadStart ombud till konstruktorn. Den har signaturen:
public delegate void ThreadStart()Public Delegate Sub ThreadStart()I följande exempel skapas och startas
ExecuteInForegrounden tråd som kör metoden. Metoden visar information om vissa trådegenskaper och kör sedan en loop där den pausar i en halv sekund och visar det förflutna antalet sekunder. När tråden har körts i minst fem sekunder avslutas loopen och tråden avslutar körningen.using System; using System.Diagnostics; using System.Threading; public class Example { public static void Main() { var th = new Thread(ExecuteInForeground); th.Start(); Thread.Sleep(1000); Console.WriteLine("Main thread ({0}) exiting...", Thread.CurrentThread.ManagedThreadId); } private static void ExecuteInForeground() { var sw = Stopwatch.StartNew(); Console.WriteLine("Thread {0}: {1}, Priority {2}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ThreadState, Thread.CurrentThread.Priority); do { Console.WriteLine("Thread {0}: Elapsed {1:N2} seconds", Thread.CurrentThread.ManagedThreadId, sw.ElapsedMilliseconds / 1000.0); Thread.Sleep(500); } while (sw.ElapsedMilliseconds <= 5000); sw.Stop(); } } // The example displays output like the following: // Thread 3: Running, Priority Normal // Thread 3: Elapsed 0.00 seconds // Thread 3: Elapsed 0.51 seconds // Main thread (1) exiting... // Thread 3: Elapsed 1.02 seconds // Thread 3: Elapsed 1.53 seconds // Thread 3: Elapsed 2.05 seconds // Thread 3: Elapsed 2.55 seconds // Thread 3: Elapsed 3.07 seconds // Thread 3: Elapsed 3.57 seconds // Thread 3: Elapsed 4.07 seconds // Thread 3: Elapsed 4.58 secondsopen System.Diagnostics open System.Threading let executeInForeground () = let sw = Stopwatch.StartNew() printfn $"Thread {Thread.CurrentThread.ManagedThreadId}: {Thread.CurrentThread.ThreadState}, Priority {Thread.CurrentThread.Priority}" while sw.ElapsedMilliseconds <= 5000 do printfn $"Thread {Thread.CurrentThread.ManagedThreadId}: Elapsed {sw.ElapsedMilliseconds / 1000L:N2} seconds" Thread.Sleep 500 sw.Stop() let th = Thread executeInForeground th.Start() Thread.Sleep 1000 printfn $"Main thread ({Thread.CurrentThread.ManagedThreadId}) exiting..." // The example displays output like the following: // Thread 3: Running, Priority Normal // Thread 3: Elapsed 0.00 seconds // Thread 3: Elapsed 0.51 seconds // Main thread (1) exiting... // Thread 3: Elapsed 1.02 seconds // Thread 3: Elapsed 1.53 seconds // Thread 3: Elapsed 2.05 seconds // Thread 3: Elapsed 2.55 seconds // Thread 3: Elapsed 3.07 seconds // Thread 3: Elapsed 3.57 seconds // Thread 3: Elapsed 4.07 seconds // Thread 3: Elapsed 4.58 secondsImports System.Diagnostics Imports System.Threading Module Example3 Public Sub Main() Dim th As New Thread(AddressOf ExecuteInForeground) th.Start() Thread.Sleep(1000) Console.WriteLine("Main thread ({0}) exiting...", Thread.CurrentThread.ManagedThreadId) End Sub Private Sub ExecuteInForeground() Dim start As DateTime = DateTime.Now Dim sw As Stopwatch = Stopwatch.StartNew() Console.WriteLine("Thread {0}: {1}, Priority {2}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ThreadState, Thread.CurrentThread.Priority) Do Console.WriteLine("Thread {0}: Elapsed {1:N2} seconds", Thread.CurrentThread.ManagedThreadId, sw.ElapsedMilliseconds / 1000) Thread.Sleep(500) Loop While sw.ElapsedMilliseconds <= 5000 sw.Stop() End Sub End Module ' The example displays output like the following: ' Thread 3: Running, Priority Normal ' Thread 3: Elapsed 0.00 seconds ' Thread 3: Elapsed 0.51 seconds ' Main thread (1) exiting... ' Thread 3: Elapsed 1.02 seconds ' Thread 3: Elapsed 1.53 seconds ' Thread 3: Elapsed 2.05 seconds ' Thread 3: Elapsed 2.55 seconds ' Thread 3: Elapsed 3.07 seconds ' Thread 3: Elapsed 3.57 seconds ' Thread 3: Elapsed 4.07 seconds ' Thread 3: Elapsed 4.58 secondsOm metoden har ett argument skickar du ett ParameterizedThreadStart ombud till konstruktorn. Den har signaturen:
public delegate void ParameterizedThreadStart(object obj)Public Delegate Sub ParameterizedThreadStart(obj As Object)Metoden som körs av ombudet kan sedan omvandla parametern (i C#) eller konvertera parametern (i Visual Basic) till lämplig typ.
Följande exempel är identiskt med det föregående, förutom att det anropar Thread(ParameterizedThreadStart) konstruktorn. Den här versionen av
ExecuteInForegroundmetoden har en enda parameter som representerar det ungefärliga antalet millisekunder som loopen ska köra.using System; using System.Diagnostics; using System.Threading; public class Example { public static void Main() { var th = new Thread(ExecuteInForeground); th.Start(4500); Thread.Sleep(1000); Console.WriteLine("Main thread ({0}) exiting...", Thread.CurrentThread.ManagedThreadId); } private static void ExecuteInForeground(Object obj) { int interval; try { interval = (int) obj; } catch (InvalidCastException) { interval = 5000; } var sw = Stopwatch.StartNew(); Console.WriteLine("Thread {0}: {1}, Priority {2}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ThreadState, Thread.CurrentThread.Priority); do { Console.WriteLine("Thread {0}: Elapsed {1:N2} seconds", Thread.CurrentThread.ManagedThreadId, sw.ElapsedMilliseconds / 1000.0); Thread.Sleep(500); } while (sw.ElapsedMilliseconds <= interval); sw.Stop(); } } // The example displays output like the following: // Thread 3: Running, Priority Normal // Thread 3: Elapsed 0.00 seconds // Thread 3: Elapsed 0.52 seconds // Main thread (1) exiting... // Thread 3: Elapsed 1.03 seconds // Thread 3: Elapsed 1.55 seconds // Thread 3: Elapsed 2.06 seconds // Thread 3: Elapsed 2.58 seconds // Thread 3: Elapsed 3.09 seconds // Thread 3: Elapsed 3.61 seconds // Thread 3: Elapsed 4.12 secondsopen System open System.Diagnostics open System.Threading let executeInForeground obj = let interval = try unbox<int> obj with :? InvalidCastException -> 5000 let sw = Stopwatch.StartNew() printfn $"Thread {Thread.CurrentThread.ManagedThreadId}: {Thread.CurrentThread.ThreadState}, Priority {Thread.CurrentThread.Priority}" while sw.ElapsedMilliseconds <= interval do printfn $"Thread {Thread.CurrentThread.ManagedThreadId}: Elapsed {sw.ElapsedMilliseconds / 1000L:N2} seconds" Thread.Sleep 500 sw.Stop() let th = Thread(ParameterizedThreadStart executeInForeground) th.Start 4500 Thread.Sleep 1000 printfn $"Main thread ({Thread.CurrentThread.ManagedThreadId}) exiting..." // The example displays output like the following: // Thread 3: Running, Priority Normal // Thread 3: Elapsed 0.00 seconds // Thread 3: Elapsed 0.52 seconds // Main thread (1) exiting... // Thread 3: Elapsed 1.03 seconds // Thread 3: Elapsed 1.55 seconds // Thread 3: Elapsed 2.06 seconds // Thread 3: Elapsed 2.58 seconds // Thread 3: Elapsed 3.09 seconds // Thread 3: Elapsed 3.61 seconds // Thread 3: Elapsed 4.12 secondsImports System.Diagnostics Imports System.Threading Module Example4 Public Sub Main() Dim th As New Thread(AddressOf ExecuteInForeground) th.Start(4500) Thread.Sleep(1000) Console.WriteLine("Main thread ({0}) exiting...", Thread.CurrentThread.ManagedThreadId) End Sub Private Sub ExecuteInForeground(obj As Object) Dim interval As Integer If IsNumeric(obj) Then interval = CInt(obj) Else interval = 5000 End If Dim start As DateTime = DateTime.Now Dim sw As Stopwatch = Stopwatch.StartNew() Console.WriteLine("Thread {0}: {1}, Priority {2}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ThreadState, Thread.CurrentThread.Priority) Do Console.WriteLine("Thread {0}: Elapsed {1:N2} seconds", Thread.CurrentThread.ManagedThreadId, sw.ElapsedMilliseconds / 1000) Thread.Sleep(500) Loop While sw.ElapsedMilliseconds <= interval sw.Stop() End Sub End Module ' The example displays output like the following: ' Thread 3: Running, Priority Normal ' Thread 3: Elapsed 0.00 seconds ' Thread 3: Elapsed 0.52 seconds ' Main thread (1) exiting... ' Thread 3: Elapsed 1.03 seconds ' Thread 3: Elapsed 1.55 seconds ' Thread 3: Elapsed 2.06 seconds ' Thread 3: Elapsed 2.58 seconds ' Thread 3: Elapsed 3.09 seconds ' Thread 3: Elapsed 3.61 seconds ' Thread 3: Elapsed 4.12 seconds
Det är inte nödvändigt att behålla en referens till ett Thread objekt när du har startat tråden. Tråden fortsätter att köras tills trådproceduren är klar.
Hämta trådobjekt
Du kan använda egenskapen static (Shared i Visual Basic) CurrentThread för att hämta en referens till den tråd som körs just nu från koden som tråden kör. I följande exempel används CurrentThread egenskapen för att visa information om huvudprogramtråden, en annan förgrundstråd, en bakgrundstråd och en trådpoolstråd.
using System;
using System.Threading;
public class Example
{
static Object obj = new Object();
public static void Main()
{
ThreadPool.QueueUserWorkItem(ShowThreadInformation);
var th1 = new Thread(ShowThreadInformation);
th1.Start();
var th2 = new Thread(ShowThreadInformation);
th2.IsBackground = true;
th2.Start();
Thread.Sleep(500);
ShowThreadInformation(null);
}
private static void ShowThreadInformation(Object state)
{
lock (obj) {
var th = Thread.CurrentThread;
Console.WriteLine("Managed thread #{0}: ", th.ManagedThreadId);
Console.WriteLine(" Background thread: {0}", th.IsBackground);
Console.WriteLine(" Thread pool thread: {0}", th.IsThreadPoolThread);
Console.WriteLine(" Priority: {0}", th.Priority);
Console.WriteLine(" Culture: {0}", th.CurrentCulture.Name);
Console.WriteLine(" UI culture: {0}", th.CurrentUICulture.Name);
Console.WriteLine();
}
}
}
// The example displays output like the following:
// Managed thread #6:
// Background thread: True
// Thread pool thread: False
// Priority: Normal
// Culture: en-US
// UI culture: en-US
//
// Managed thread #3:
// Background thread: True
// Thread pool thread: True
// Priority: Normal
// Culture: en-US
// UI culture: en-US
//
// Managed thread #4:
// Background thread: False
// Thread pool thread: False
// Priority: Normal
// Culture: en-US
// UI culture: en-US
//
// Managed thread #1:
// Background thread: False
// Thread pool thread: False
// Priority: Normal
// Culture: en-US
// UI culture: en-US
open System.Threading
let obj = obj ()
let showThreadInformation (state: obj) =
lock obj (fun () ->
let th = Thread.CurrentThread
printfn $"Managed thread #{th.ManagedThreadId}: "
printfn $" Background thread: {th.IsBackground}"
printfn $" Thread pool thread: {th.IsThreadPoolThread}"
printfn $" Priority: {th.Priority}"
printfn $" Culture: {th.CurrentCulture.Name}"
printfn $" UI culture: {th.CurrentUICulture.Name}"
printfn "")
ThreadPool.QueueUserWorkItem showThreadInformation |> ignore
let th1 = Thread(ParameterizedThreadStart showThreadInformation)
th1.Start()
let th2 = Thread(ParameterizedThreadStart showThreadInformation)
th2.IsBackground <- true
th2.Start()
Thread.Sleep 500
showThreadInformation ()
// The example displays output like the following:
// Managed thread #6:
// Background thread: True
// Thread pool thread: False
// Priority: Normal
// Culture: en-US
// UI culture: en-US
//
// Managed thread #3:
// Background thread: True
// Thread pool thread: True
// Priority: Normal
// Culture: en-US
// UI culture: en-US
//
// Managed thread #4:
// Background thread: False
// Thread pool thread: False
// Priority: Normal
// Culture: en-US
// UI culture: en-US
//
// Managed thread #1:
// Background thread: False
// Thread pool thread: False
// Priority: Normal
// Culture: en-US
// UI culture: en-US
Imports System.Threading
Module Example2
Private lock As New Object()
Public Sub Main()
ThreadPool.QueueUserWorkItem(AddressOf ShowThreadInformation)
Dim th1 As New Thread(AddressOf ShowThreadInformation)
th1.Start()
Dim th2 As New Thread(AddressOf ShowThreadInformation)
th2.IsBackground = True
th2.Start()
Thread.Sleep(500)
ShowThreadInformation(Nothing)
End Sub
Private Sub ShowThreadInformation(state As Object)
SyncLock lock
Dim th As Thread = Thread.CurrentThread
Console.WriteLine("Managed thread #{0}: ", th.ManagedThreadId)
Console.WriteLine(" Background thread: {0}", th.IsBackground)
Console.WriteLine(" Thread pool thread: {0}", th.IsThreadPoolThread)
Console.WriteLine(" Priority: {0}", th.Priority)
Console.WriteLine(" Culture: {0}", th.CurrentCulture.Name)
Console.WriteLine(" UI culture: {0}", th.CurrentUICulture.Name)
Console.WriteLine()
End SyncLock
End Sub
End Module
' The example displays output like the following:
' ' Managed thread #6:
' Background thread: True
' Thread pool thread: False
' Priority: Normal
' Culture: en-US
' UI culture: en-US
'
' Managed thread #3:
' Background thread: True
' Thread pool thread: True
' Priority: Normal
' Culture: en-US
' UI culture: en-US
'
' Managed thread #4:
' Background thread: False
' Thread pool thread: False
' Priority: Normal
' Culture: en-US
' UI culture: en-US
'
' Managed thread #1:
' Background thread: False
' Thread pool thread: False
' Priority: Normal
' Culture: en-US
' UI culture: en-US
Förgrunds- och bakgrundstrådar
Instanser av Thread klassen representerar antingen förgrundstrådar eller bakgrundstrådar. Bakgrundstrådar är identiska med förgrundstrådar med ett undantag: en bakgrundstråd håller inte en process igång om alla förgrundstrådar har avslutats. När alla förgrundstrådar har stoppats, stoppar körtiden alla bakgrundstrådar och stänger ner.
Som standard körs följande trådar i förgrunden:
Huvudtråden för applikationen.
Alla trådar som skapats genom att anropa en Thread klasskonstruktor.
Följande trådar körs som standard i bakgrunden:
Trådar från trådpoolen, som kommer från en pool med arbets-trådar som underhålls av run-timemiljön. Du kan konfigurera trådpoolen och schemalägga arbete med trådpoolstrådar med hjälp ThreadPool av klassen .
Note
Aktivitetsbaserade asynkrona åtgärder körs automatiskt på trådpooltrådar. Aktivitetsbaserade asynkrona åtgärder använder Task klasserna och Task<TResult> för att implementera det aktivitetsbaserade asynkrona mönstret.
Alla trådar som går in i den hanterade körningsmiljön från ohanterad kod.
Du kan ändra en tråd så att den körs i bakgrunden genom att ange egenskapen IsBackground när som helst. Bakgrundstrådar är användbara för alla åtgärder som ska fortsätta så länge ett program körs, men bör inte hindra programmet från att avslutas, till exempel övervakning av filsystemändringar eller inkommande socketanslutningar.
I följande exempel visas skillnaden mellan förgrundstrådar och bakgrundstrådar. Det är som det första exemplet i avsnittet Starta en tråd , förutom att den anger att tråden ska köras i bakgrunden innan den startas. Som utdata visar avbryts loopen innan den körs i fem sekunder.
using System;
using System.Diagnostics;
using System.Threading;
public class Example
{
public static void Main()
{
var th = new Thread(ExecuteInForeground);
th.IsBackground = true;
th.Start();
Thread.Sleep(1000);
Console.WriteLine("Main thread ({0}) exiting...",
Thread.CurrentThread.ManagedThreadId);
}
private static void ExecuteInForeground()
{
var sw = Stopwatch.StartNew();
Console.WriteLine("Thread {0}: {1}, Priority {2}",
Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.ThreadState,
Thread.CurrentThread.Priority);
do {
Console.WriteLine("Thread {0}: Elapsed {1:N2} seconds",
Thread.CurrentThread.ManagedThreadId,
sw.ElapsedMilliseconds / 1000.0);
Thread.Sleep(500);
} while (sw.ElapsedMilliseconds <= 5000);
sw.Stop();
}
}
// The example displays output like the following:
// Thread 3: Background, Priority Normal
// Thread 3: Elapsed 0.00 seconds
// Thread 3: Elapsed 0.51 seconds
// Main thread (1) exiting...
open System.Diagnostics
open System.Threading
let executeInForeground () =
let sw = Stopwatch.StartNew()
printfn $"Thread {Thread.CurrentThread.ManagedThreadId}: {Thread.CurrentThread.ThreadState}, Priority {Thread.CurrentThread.Priority}"
while sw.ElapsedMilliseconds <= 5000 do
printfn $"Thread {Thread.CurrentThread.ManagedThreadId}: Elapsed {sw.ElapsedMilliseconds / 1000L:N2} seconds"
Thread.Sleep 500
sw.Stop()
let th = Thread executeInForeground
th.IsBackground <- true
th.Start()
Thread.Sleep 1000
printfn $"Main thread ({Thread.CurrentThread.ManagedThreadId}) exiting..."
// The example displays output like the following:
// Thread 3: Background, Priority Normal
// Thread 3: Elapsed 0.00 seconds
// Thread 3: Elapsed 0.51 seconds
// Main thread (1) exiting...
Imports System.Diagnostics
Imports System.Threading
Module Example1
Public Sub Main()
Dim th As New Thread(AddressOf ExecuteInForeground)
th.IsBackground = True
th.Start()
Thread.Sleep(1000)
Console.WriteLine("Main thread ({0}) exiting...", Thread.CurrentThread.ManagedThreadId)
End Sub
Private Sub ExecuteInForeground()
Dim start As DateTime = DateTime.Now
Dim sw As Stopwatch = Stopwatch.StartNew()
Console.WriteLine("Thread {0}: {1}, Priority {2}",
Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.ThreadState,
Thread.CurrentThread.Priority)
Do
Console.WriteLine("Thread {0}: Elapsed {1:N2} seconds",
Thread.CurrentThread.ManagedThreadId,
sw.ElapsedMilliseconds / 1000)
Thread.Sleep(500)
Loop While sw.ElapsedMilliseconds <= 5000
sw.Stop()
End Sub
End Module
' The example displays output like the following:
' Thread 3: Background, Priority Normal
' Thread 3: Elapsed 0.00 seconds
' Thread 3: Elapsed 0.51 seconds
' Main thread (1) exiting...
Kultur och trådar
Varje tråd har en kultur som representeras av CurrentCulture egenskapen och en UI-kultur som representeras av CurrentUICulture egenskapen. Den aktuella kulturen stöder kulturkänsliga åtgärder, till exempel parsning och formatering, strängjämförelse och sortering, och styr även skrivsystemet och kalendern som används av en tråd. Den aktuella användargränssnittskulturen tillhandahåller kulturkänslig hämtning av resurser i resursfiler.
Important
Egenskaperna CurrentCulture och CurrentUICulture fungerar inte tillförlitligt när de används med någon annan tråd än den aktuella tråden. En InvalidOperationException utlöses om en tråd försöker läsa eller skriva dessa egenskaper på en annan tråd. Vi rekommenderar att du använder CultureInfo.CurrentCulture egenskaperna och CultureInfo.CurrentUICulture för att hämta och ange den aktuella kulturen.
När en ny tråd instansieras definieras dess kultur och användargränssnittskultur av den aktuella systemkulturen och användargränssnittskulturen, och inte av kulturen och användargränssnittskulturen i tråden som den nya tråden skapas från. Detta innebär till exempel att om den nuvarande systemkulturen är engelska (USA) och den nuvarande kulturen i den primära programtråden är franska (Frankrike), är kulturen i en ny tråd som skapas genom att anropa Thread(ParameterizedThreadStart) konstruktorn från den primära tråden engelska (USA) och inte franska (Frankrike). Mer information finns i avsnittet "Kultur och trådar" i ämnet för klassen CultureInfo.
Important
Detta gäller inte för trådar som kör asynkrona åtgärder för appar som riktar sig till .NET Framework 4.6 och senare versioner. I det här fallet är kultur- och användargränssnittskulturen en del av en asynkron åtgärds kontext. tråden där en asynkron åtgärd körs som standard ärver kulturen och användargränssnittskulturen i den tråd som den asynkrona åtgärden startades från. För mer information, se avsnittet "Kultur och uppgiftsbaserade asynkrona operationer" i klassbeskrivningarna CultureInfo.
Du kan göra något av följande för att se till att alla trådar som körs i ett program delar samma kultur och användargränssnittskultur:
Du kan skicka ett CultureInfo-objekt som representerar den kulturen till delegaten ParameterizedThreadStart eller metoden ThreadPool.QueueUserWorkItem(WaitCallback, Object).
För appar som körs på .NET Framework 4.5 och senare versioner kan du definiera kulturen och användargränssnittskulturen som ska tilldelas till alla trådar som skapats i en programdomän genom att ange värdet CultureInfo.DefaultThreadCurrentCulture för egenskaperna och CultureInfo.DefaultThreadCurrentUICulture . Observera att det här är en domäninställning per program.
För mer information och exempel, se avsnittet "Kultur och trådar" i CultureInfo klasskommentarerna.
Hämta information om och kontrollera trådar
Du kan hämta ett antal egenskapsvärden som ger information om en tråd. I vissa fall kan du också ange dessa egenskapsvärden för att styra trådens funktion. Dessa trådegenskaper är:
Ett namn. Name är en skriven gång-egenskap som du kan använda för att identifiera en tråd. Standardvärdet är
null.En hash-kod som du kan hämta genom att anropa GetHashCode metoden. Hash-koden kan användas för att unikt identifiera en tråd. under trådens livslängd kommer dess hash-kod inte att kollidera med värdet från någon annan tråd, oavsett vilken programdomän du hämtar värdet från.
Ett tråd-ID. Värdet för den skrivskyddade ManagedThreadId egenskapen tilldelas av körtiden och identifierar unikt en tråd inom sin process.
Note
Ett ThreadId för operativsystemet har ingen fast relation till en hanterad tråd, eftersom en ohanterad värd kan styra relationen mellan hanterade och ohanterade trådar. Mer specifikt kan en sofistikerad värd använda CLR Hosting API för att schemalägga många hanterade trådar mot samma operativsystemtråd, eller för att flytta en hanterad tråd mellan olika operativsystemtrådar.
Trådens aktuella tillstånd. Under hela dess existens finns en tråd alltid i ett eller flera av de tillstånd som definieras av egenskapen ThreadState .
En schemaläggningsprioritetsnivå som definieras av egenskapen ThreadPriority . Även om du kan ange det här värdet för att begära en tråds prioritet, är det inte garanterat att det respekteras av operativsystemet.
Den skrivskyddade IsThreadPoolThread egenskapen, som anger om en tråd är en trådpoolstråd.
Egenskapen IsBackground. Mer information finns i avsnittet Förgrunds- och bakgrundstrådar .
Konstruktorer
| Name | Description |
|---|---|
| Thread(ParameterizedThreadStart, Int32) |
Initierar en ny instans av Thread klassen och anger ett ombud som tillåter att ett objekt skickas till tråden när tråden startas och anger den maximala stackstorleken för tråden. |
| Thread(ParameterizedThreadStart) |
Initierar en ny instans av Thread klassen och anger ett ombud som gör att ett objekt kan skickas till tråden när tråden startas. |
| Thread(ThreadStart, Int32) |
Initierar en ny instans av Thread klassen och anger den maximala stackstorleken för tråden. |
| Thread(ThreadStart) |
Initierar en ny instans av Thread klassen. |
Egenskaper
| Name | Description |
|---|---|
| ApartmentState |
Föråldrad.
Föråldrad.
Hämtar eller anger lägenhetstillståndet för den här tråden. |
| CurrentContext |
Hämtar den aktuella kontexten där tråden körs. |
| CurrentCulture |
Hämtar eller anger kulturen för den aktuella tråden. |
| CurrentPrincipal |
Hämtar eller anger trådens aktuella huvudnamn (för rollbaserad säkerhet). |
| CurrentThread |
Hämtar den tråd som körs just nu. |
| CurrentUICulture |
Hämtar eller anger den aktuella kultur som används av Resource Manager för att söka efter kulturspecifika resurser vid körning. |
| ExecutionContext |
Hämtar ett ExecutionContext objekt som innehåller information om de olika kontexterna i den aktuella tråden. |
| IsAlive |
Hämtar ett värde som anger körningsstatusen för den aktuella tråden. |
| IsBackground |
Hämtar eller anger ett värde som anger om en tråd är en bakgrundstråd eller inte. |
| IsThreadPoolThread |
Hämtar ett värde som anger om en tråd tillhör den hanterade trådpoolen eller inte. |
| ManagedThreadId |
Hämtar en unik identifierare för den aktuella hanterade tråden. |
| Name |
Hämtar eller anger namnet på tråden. |
| Priority |
Hämtar eller anger ett värde som anger schemaläggningsprioriteten för en tråd. |
| ThreadState |
Hämtar ett värde som innehåller tillstånden för den aktuella tråden. |
Metoder
| Name | Description |
|---|---|
| Abort() |
Föråldrad.
Genererar en ThreadAbortException i tråden som den anropas på för att påbörja processen med att avsluta tråden. Att anropa den här metoden avslutar vanligtvis tråden. |
| Abort(Object) |
Föråldrad.
Genererar en ThreadAbortException i tråden som den anropas på för att påbörja processen med att avsluta tråden och samtidigt tillhandahålla undantagsinformation om trådavslutningen. Att anropa den här metoden avslutar vanligtvis tråden. |
| AllocateDataSlot() |
Allokerar ett namnlöst datafack på alla trådar. För bättre prestanda använder du fält som är markerade med ThreadStaticAttribute attributet i stället. |
| AllocateNamedDataSlot(String) |
Allokerar ett namngivet datafack på alla trådar. För bättre prestanda använder du fält som är markerade med ThreadStaticAttribute attributet i stället. |
| BeginCriticalRegion() |
Meddelar en värd att körningen är på väg att ange en region med kod där effekterna av en tråd avbryter eller ohanterade undantag kan äventyra andra uppgifter i programdomänen. |
| BeginThreadAffinity() |
Meddelar en värd att hanterad kod är på väg att köra instruktioner som är beroende av identiteten för den aktuella fysiska operativsystemtråden. |
| DisableComObjectEagerCleanup() |
Inaktiverar automatisk rensning av runtime-anropsbara omslutningar (RCW) för den aktuella tråden. |
| EndCriticalRegion() |
Meddelar en värd att körningen är på väg att ange en kodregion där effekterna av en tråd avbryts eller ett ohanterat undantag begränsas till den aktuella aktiviteten. |
| EndThreadAffinity() |
Meddelar en värd som hanterad kod har slutfört körningsinstruktioner som är beroende av identiteten för den aktuella fysiska operativsystemtråden. |
| Equals(Object) |
Avgör om det angivna objektet är lika med det aktuella objektet. (Ärvd från Object) |
| Finalize() |
Säkerställer att resurser frigörs och att andra rensningsåtgärder utförs när skräpinsamlaren återtar Thread objektet. |
| FreeNamedDataSlot(String) |
Eliminerar associationen mellan ett namn och ett fack för alla trådar i processen. För bättre prestanda använder du fält som är markerade med ThreadStaticAttribute attributet i stället. |
| GetApartmentState() |
Returnerar ett ApartmentState värde som anger lägenhetstillståndet. |
| GetCompressedStack() |
Föråldrad.
Föråldrad.
Returnerar ett CompressedStack objekt som kan användas för att avbilda stacken för den aktuella tråden. |
| GetCurrentProcessorId() |
Hämtar ett ID som används för att ange vilken processor den aktuella tråden körs på. |
| GetData(LocalDataStoreSlot) |
Hämtar värdet från det angivna facket i den aktuella tråden inom den aktuella trådens aktuella domän. För bättre prestanda använder du fält som är markerade med ThreadStaticAttribute attributet i stället. |
| GetDomain() |
Returnerar den aktuella domänen där den aktuella tråden körs. |
| GetDomainID() |
Returnerar en unik programdomänidentifierare. |
| GetHashCode() |
Returnerar en hash-kod för den aktuella tråden. |
| GetHashCode() |
Fungerar som standard-hash-funktion. (Ärvd från Object) |
| GetNamedDataSlot(String) |
Letar upp ett namngivet datafack. För bättre prestanda använder du fält som är markerade med ThreadStaticAttribute attributet i stället. |
| GetType() |
Hämtar den aktuella instansen Type . (Ärvd från Object) |
| Interrupt() |
Avbryter en tråd som är i WaitSleepJoin trådtillståndet. |
| Join() |
Blockerar den anropande tråden tills tråden som representeras av den här instansen avslutas, samtidigt som standard-COM och |
| Join(Int32) |
Blockerar den anropande tråden tills tråden som representeras av den här instansen avslutas eller den angivna tiden förflutit, samtidigt som com- och SendMessage-standardpumpning fortsätter. |
| Join(TimeSpan) |
Blockerar den anropande tråden tills tråden som representeras av den här instansen avslutas eller den angivna tiden förflutit, samtidigt som com- och SendMessage-standardpumpning fortsätter. |
| MemberwiseClone() |
Skapar en ytlig kopia av den aktuella Object. (Ärvd från Object) |
| MemoryBarrier() |
Synkroniserar minnesåtkomst på följande sätt: Processorn som kör den aktuella tråden kan inte ändra ordning på instruktioner på ett sådant sätt att minnet kommer åt innan anropet att MemoryBarrier() köras efter minnesåtkomster som följer anropet till MemoryBarrier(). |
| ResetAbort() |
Föråldrad.
Avbryter en Abort(Object) begärd för den aktuella tråden. |
| Resume() |
Föråldrad.
Föråldrad.
Föråldrad.
Återupptar en tråd som har pausats. |
| SetApartmentState(ApartmentState) |
Anger lägenhetstillståndet för en tråd innan den startas. |
| SetCompressedStack(CompressedStack) |
Föråldrad.
Föråldrad.
Tillämpar en insamlad CompressedStack på den aktuella tråden. |
| SetData(LocalDataStoreSlot, Object) |
Anger data i det angivna facket på den tråd som körs för den aktuella tråden för den aktuella domänen. För bättre prestanda använder du fält som markerats ThreadStaticAttribute med attributet i stället. |
| Sleep(Int32) |
Pausar den aktuella tråden för det angivna antalet millisekunder. |
| Sleep(TimeSpan) |
Pausar den aktuella tråden under den angivna tiden. |
| SpinWait(Int32) |
Gör att en tråd väntar på det antal gånger som definierats av parametern |
| Start() |
Gör att operativsystemet ändrar tillståndet för den aktuella instansen till Running. |
| Start(Object) |
Gör att operativsystemet ändrar tillståndet för den aktuella instansen till Runningoch eventuellt tillhandahåller ett objekt som innehåller data som ska användas av metoden som tråden kör. |
| Suspend() |
Föråldrad.
Föråldrad.
Föråldrad.
Antingen pausar tråden, eller om tråden redan är pausad, har ingen effekt. |
| ToString() |
Returnerar en sträng som representerar det aktuella objektet. (Ärvd från Object) |
| TrySetApartmentState(ApartmentState) |
Anger lägenhetstillståndet för en tråd innan den startas. |
| UnsafeStart() |
Gör att operativsystemet ändrar tillståndet för den aktuella instansen till Running. |
| UnsafeStart(Object) |
Gör att operativsystemet ändrar tillståndet för den aktuella instansen till Runningoch eventuellt tillhandahåller ett objekt som innehåller data som ska användas av metoden som tråden kör. |
| VolatileRead(Byte) |
Föråldrad.
Läser värdet för ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas efter den här metoden i koden kan processorn inte flytta den före den här metoden. |
| VolatileRead(Double) |
Föråldrad.
Läser värdet för ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas efter den här metoden i koden kan processorn inte flytta den före den här metoden. |
| VolatileRead(Int16) |
Föråldrad.
Läser värdet för ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas efter den här metoden i koden kan processorn inte flytta den före den här metoden. |
| VolatileRead(Int32) |
Föråldrad.
Läser värdet för ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas efter den här metoden i koden kan processorn inte flytta den före den här metoden. |
| VolatileRead(Int64) |
Föråldrad.
Läser värdet för ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas efter den här metoden i koden kan processorn inte flytta den före den här metoden. |
| VolatileRead(IntPtr) |
Föråldrad.
Läser värdet för ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas efter den här metoden i koden kan processorn inte flytta den före den här metoden. |
| VolatileRead(Object) |
Föråldrad.
Läser värdet för ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas efter den här metoden i koden kan processorn inte flytta den före den här metoden. |
| VolatileRead(SByte) |
Föråldrad.
Läser värdet för ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas efter den här metoden i koden kan processorn inte flytta den före den här metoden. |
| VolatileRead(Single) |
Föråldrad.
Läser värdet för ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas efter den här metoden i koden kan processorn inte flytta den före den här metoden. |
| VolatileRead(UInt16) |
Föråldrad.
Läser värdet för ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas efter den här metoden i koden kan processorn inte flytta den före den här metoden. |
| VolatileRead(UInt32) |
Föråldrad.
Läser värdet för ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas efter den här metoden i koden kan processorn inte flytta den före den här metoden. |
| VolatileRead(UInt64) |
Föråldrad.
Läser värdet för ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas efter den här metoden i koden kan processorn inte flytta den före den här metoden. |
| VolatileRead(UIntPtr) |
Föråldrad.
Läser värdet för ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas efter den här metoden i koden kan processorn inte flytta den före den här metoden. |
| VolatileWrite(Byte, Byte) |
Föråldrad.
Skriver ett värde till ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas före den här metoden i koden kan processorn inte flytta den efter den här metoden. |
| VolatileWrite(Double, Double) |
Föråldrad.
Skriver ett värde till ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas före den här metoden i koden kan processorn inte flytta den efter den här metoden. |
| VolatileWrite(Int16, Int16) |
Föråldrad.
Skriver ett värde till ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas före den här metoden i koden kan processorn inte flytta den efter den här metoden. |
| VolatileWrite(Int32, Int32) |
Föråldrad.
Skriver ett värde till ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas före den här metoden i koden kan processorn inte flytta den efter den här metoden. |
| VolatileWrite(Int64, Int64) |
Föråldrad.
Skriver ett värde till ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas före den här metoden i koden kan processorn inte flytta den efter den här metoden. |
| VolatileWrite(IntPtr, IntPtr) |
Föråldrad.
Skriver ett värde till ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas före den här metoden i koden kan processorn inte flytta den efter den här metoden. |
| VolatileWrite(Object, Object) |
Föråldrad.
Skriver ett värde till ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas före den här metoden i koden kan processorn inte flytta den efter den här metoden. |
| VolatileWrite(SByte, SByte) |
Föråldrad.
Skriver ett värde till ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas före den här metoden i koden kan processorn inte flytta den efter den här metoden. |
| VolatileWrite(Single, Single) |
Föråldrad.
Skriver ett värde till ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas före den här metoden i koden kan processorn inte flytta den efter den här metoden. |
| VolatileWrite(UInt16, UInt16) |
Föråldrad.
Skriver ett värde till ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas före den här metoden i koden kan processorn inte flytta den efter den här metoden. |
| VolatileWrite(UInt32, UInt32) |
Föråldrad.
Skriver ett värde till ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas före den här metoden i koden kan processorn inte flytta den efter den här metoden. |
| VolatileWrite(UInt64, UInt64) |
Föråldrad.
Skriver ett värde till ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas före den här metoden i koden kan processorn inte flytta den efter den här metoden. |
| VolatileWrite(UIntPtr, UIntPtr) |
Föråldrad.
Skriver ett värde till ett fält. På system som kräver det infogar en minnesbarriär som hindrar processorn från att ordna om minnesåtgärder på följande sätt: Om en läsning eller skrivning visas före den här metoden i koden kan processorn inte flytta den efter den här metoden. |
| Yield() |
Gör att den anropande tråden ger körning till en annan tråd som är redo att köras på den aktuella processorn. Operativsystemet väljer den tråd som ska ge resultat till. |
Explicita gränssnittsimplementeringar
| Name | Description |
|---|---|
| _Thread.GetIDsOfNames(Guid, IntPtr, UInt32, UInt32, IntPtr) |
Mappar en uppsättning namn till en motsvarande uppsättning av sändningsidentifierare. |
| _Thread.GetTypeInfo(UInt32, UInt32, IntPtr) |
Hämtar typinformationen för ett objekt, som sedan kan användas för att hämta typinformationen för ett gränssnitt. |
| _Thread.GetTypeInfoCount(UInt32) |
Hämtar antalet typinformationsgränssnitt som ett objekt tillhandahåller (antingen 0 eller 1). |
| _Thread.Invoke(UInt32, Guid, UInt32, Int16, IntPtr, IntPtr, IntPtr, IntPtr) |
Ger åtkomst till egenskaper och metoder som exponeras av ett objekt. |
Gäller för
Trådsäkerhet
Den här typen är trådsäker.