TaskScheduler TaskScheduler TaskScheduler TaskScheduler Class

Definition

Stellt ein Objekt dar, das die Einreihung von Aufgaben in Threads auf niedriger Ebene behandelt.Represents an object that handles the low-level work of queuing tasks onto threads.

public ref class TaskScheduler abstract
public abstract class TaskScheduler
type TaskScheduler = class
Public MustInherit Class TaskScheduler
Vererbung
TaskSchedulerTaskSchedulerTaskSchedulerTaskScheduler

Beispiele

Das folgende Beispiel stammt aus den Beispielen für die parallele Programmierung mit dem .NET Framework 4 auf der MSDN Code Gallery-Website.The following example is taken from the Samples for Parallel Programming with the .NET Framework 4 on the MSDN Code Gallery Web site. Es wird ein benutzerdefinierter Taskplaner erstellt, der die Anzahl der Threads einschränkt, die von der APP verwendet werden.It creates a custom task scheduler that limits the number of threads used by the app. Anschließend werden zwei Aufgaben Sätze gestartet, und es werden Informationen über die Aufgabe und den Thread angezeigt, in dem die Aufgabe ausgeführt wird.It then launches two sets of tasks and displays information about the task and the thread on which the task is executing.

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

class Example
{
   static void Main()
   {
       // Create a scheduler that uses two threads. 
       LimitedConcurrencyLevelTaskScheduler lcts = new LimitedConcurrencyLevelTaskScheduler(2);
       List<Task> tasks = new List<Task>();
       
       // Create a TaskFactory and pass it our custom scheduler. 
       TaskFactory factory = new TaskFactory(lcts);
       CancellationTokenSource cts = new CancellationTokenSource();
       
       // Use our factory to run a set of tasks. 
       Object lockObj = new Object();
       int outputItem = 0;
       
       for (int tCtr = 0; tCtr <= 4; tCtr++) {
          int iteration = tCtr;
          Task t = factory.StartNew(() => {
                                       for (int i = 0; i < 1000; i++) {
                                          lock (lockObj) {
                                             Console.Write("{0} in task t-{1} on thread {2}   ", 
                                                           i, iteration, Thread.CurrentThread.ManagedThreadId);
                                             outputItem++;
                                             if (outputItem % 3 == 0)
                                                Console.WriteLine();
                                          }
                                       }                   
                                    }, cts.Token);
          tasks.Add(t);                      
      }
      // Use it to run a second set of tasks.                       
      for (int tCtr = 0; tCtr <= 4; tCtr++) {
         int iteration = tCtr;
         Task t1 = factory.StartNew(() => {
                                       for (int outer = 0; outer <= 10; outer++) {
                                          for (int i = 0x21; i <= 0x7E; i++) {
                                             lock (lockObj) {
                                                Console.Write("'{0}' in task t1-{1} on thread {2}   ", 
                                                              Convert.ToChar(i), iteration, Thread.CurrentThread.ManagedThreadId);
                                                outputItem++;
                                                if (outputItem % 3 == 0)
                                                   Console.WriteLine();
                                             } 
                                          }
                                       }                                           
                                    }, cts.Token);           
         tasks.Add(t1);
      }
      
      // Wait for the tasks to complete before displaying a completion message.
      Task.WaitAll(tasks.ToArray());
      cts.Dispose();
      Console.WriteLine("\n\nSuccessful completion.");
   }
}

// Provides a task scheduler that ensures a maximum concurrency level while 
// running on top of the thread pool.
public class LimitedConcurrencyLevelTaskScheduler : TaskScheduler
{
   // Indicates whether the current thread is processing work items.
   [ThreadStatic]
   private static bool _currentThreadIsProcessingItems;

  // The list of tasks to be executed 
   private readonly LinkedList<Task> _tasks = new LinkedList<Task>(); // protected by lock(_tasks)

   // The maximum concurrency level allowed by this scheduler. 
   private readonly int _maxDegreeOfParallelism;

   // Indicates whether the scheduler is currently processing work items. 
   private int _delegatesQueuedOrRunning = 0;

   // Creates a new instance with the specified degree of parallelism. 
   public LimitedConcurrencyLevelTaskScheduler(int maxDegreeOfParallelism)
   {
       if (maxDegreeOfParallelism < 1) throw new ArgumentOutOfRangeException("maxDegreeOfParallelism");
       _maxDegreeOfParallelism = maxDegreeOfParallelism;
   }

   // Queues a task to the scheduler. 
   protected sealed override void QueueTask(Task task)
   {
      // Add the task to the list of tasks to be processed.  If there aren't enough 
      // delegates currently queued or running to process tasks, schedule another. 
       lock (_tasks)
       {
           _tasks.AddLast(task);
           if (_delegatesQueuedOrRunning < _maxDegreeOfParallelism)
           {
               ++_delegatesQueuedOrRunning;
               NotifyThreadPoolOfPendingWork();
           }
       }
   }

   // Inform the ThreadPool that there's work to be executed for this scheduler. 
   private void NotifyThreadPoolOfPendingWork()
   {
       ThreadPool.UnsafeQueueUserWorkItem(_ =>
       {
           // Note that the current thread is now processing work items.
           // This is necessary to enable inlining of tasks into this thread.
           _currentThreadIsProcessingItems = true;
           try
           {
               // Process all available items in the queue.
               while (true)
               {
                   Task item;
                   lock (_tasks)
                   {
                       // When there are no more items to be processed,
                       // note that we're done processing, and get out.
                       if (_tasks.Count == 0)
                       {
                           --_delegatesQueuedOrRunning;
                           break;
                       }

                       // Get the next item from the queue
                       item = _tasks.First.Value;
                       _tasks.RemoveFirst();
                   }

                   // Execute the task we pulled out of the queue
                   base.TryExecuteTask(item);
               }
           }
           // We're done processing items on the current thread
           finally { _currentThreadIsProcessingItems = false; }
       }, null);
   }

   // Attempts to execute the specified task on the current thread. 
   protected sealed override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
   {
       // If this thread isn't already processing a task, we don't support inlining
       if (!_currentThreadIsProcessingItems) return false;

       // If the task was previously queued, remove it from the queue
       if (taskWasPreviouslyQueued) 
          // Try to run the task. 
          if (TryDequeue(task)) 
            return base.TryExecuteTask(task);
          else
             return false; 
       else 
          return base.TryExecuteTask(task);
   }

   // Attempt to remove a previously scheduled task from the scheduler. 
   protected sealed override bool TryDequeue(Task task)
   {
       lock (_tasks) return _tasks.Remove(task);
   }

   // Gets the maximum concurrency level supported by this scheduler. 
   public sealed override int MaximumConcurrencyLevel { get { return _maxDegreeOfParallelism; } }

   // Gets an enumerable of the tasks currently scheduled on this scheduler. 
   protected sealed override IEnumerable<Task> GetScheduledTasks()
   {
       bool lockTaken = false;
       try
       {
           Monitor.TryEnter(_tasks, ref lockTaken);
           if (lockTaken) return _tasks;
           else throw new NotSupportedException();
       }
       finally
       {
           if (lockTaken) Monitor.Exit(_tasks);
       }
   }
}
// The following is a portion of the output from a single run of the example:
//    'T' in task t1-4 on thread 3   'U' in task t1-4 on thread 3   'V' in task t1-4 on thread 3   
//    'W' in task t1-4 on thread 3   'X' in task t1-4 on thread 3   'Y' in task t1-4 on thread 3   
//    'Z' in task t1-4 on thread 3   '[' in task t1-4 on thread 3   '\' in task t1-4 on thread 3   
//    ']' in task t1-4 on thread 3   '^' in task t1-4 on thread 3   '_' in task t1-4 on thread 3   
//    '`' in task t1-4 on thread 3   'a' in task t1-4 on thread 3   'b' in task t1-4 on thread 3   
//    'c' in task t1-4 on thread 3   'd' in task t1-4 on thread 3   'e' in task t1-4 on thread 3   
//    'f' in task t1-4 on thread 3   'g' in task t1-4 on thread 3   'h' in task t1-4 on thread 3   
//    'i' in task t1-4 on thread 3   'j' in task t1-4 on thread 3   'k' in task t1-4 on thread 3   
//    'l' in task t1-4 on thread 3   'm' in task t1-4 on thread 3   'n' in task t1-4 on thread 3   
//    'o' in task t1-4 on thread 3   'p' in task t1-4 on thread 3   ']' in task t1-2 on thread 4   
//    '^' in task t1-2 on thread 4   '_' in task t1-2 on thread 4   '`' in task t1-2 on thread 4   
//    'a' in task t1-2 on thread 4   'b' in task t1-2 on thread 4   'c' in task t1-2 on thread 4   
//    'd' in task t1-2 on thread 4   'e' in task t1-2 on thread 4   'f' in task t1-2 on thread 4   
//    'g' in task t1-2 on thread 4   'h' in task t1-2 on thread 4   'i' in task t1-2 on thread 4   
//    'j' in task t1-2 on thread 4   'k' in task t1-2 on thread 4   'l' in task t1-2 on thread 4   
//    'm' in task t1-2 on thread 4   'n' in task t1-2 on thread 4   'o' in task t1-2 on thread 4   
//    'p' in task t1-2 on thread 4   'q' in task t1-2 on thread 4   'r' in task t1-2 on thread 4   
//    's' in task t1-2 on thread 4   't' in task t1-2 on thread 4   'u' in task t1-2 on thread 4   
//    'v' in task t1-2 on thread 4   'w' in task t1-2 on thread 4   'x' in task t1-2 on thread 4   
//    'y' in task t1-2 on thread 4   'z' in task t1-2 on thread 4   '{' in task t1-2 on thread 4   
//    '|' in task t1-2 on thread 4   '}' in task t1-2 on thread 4   '~' in task t1-2 on thread 4   
//    'q' in task t1-4 on thread 3   'r' in task t1-4 on thread 3   's' in task t1-4 on thread 3   
//    't' in task t1-4 on thread 3   'u' in task t1-4 on thread 3   'v' in task t1-4 on thread 3   
//    'w' in task t1-4 on thread 3   'x' in task t1-4 on thread 3   'y' in task t1-4 on thread 3   
//    'z' in task t1-4 on thread 3   '{' in task t1-4 on thread 3   '|' in task t1-4 on thread 3  
Imports System.Collections.Generic
Imports System.Threading
Imports System.Threading.Tasks

Module Example
   Sub Main()
      ' Create a scheduler that uses two threads. 
      Dim lcts As New LimitedConcurrencyLevelTaskScheduler(2)
      Dim tasks As New List(Of Task)()
      
      ' Create a TaskFactory and pass it our custom scheduler. 
      Dim factory As New TaskFactory(lcts)
      Dim cts As New CancellationTokenSource()
      
      ' Use our factory to run a set of tasks. 
      Dim objLock As New Object()      
      Dim outputItem As Integer 
      For tCtr As Integer = 0 To 4
         Dim iteration As Integer = tCtr
         Dim t As Task = factory.StartNew(Sub()
                                             For i As Integer = 1 To 1000
                                                SyncLock objLock
                                                   Console.Write("{0} in task t-{1} on thread {2}   ", 
                                                   i, iteration, Thread.CurrentThread.ManagedThreadId)
                                                   outputItem += 1
                                                   If outputItem Mod 3 = 0 Then Console.WriteLine()
                                                End SyncLock
                                             Next 
                                          End Sub,
                                cts.Token)
         tasks.Add(t)
      Next 
      ' Use it to run a second set of tasks.                       
      For tCtr As Integer = 0 To 4
         Dim iteration As Integer = tCtr
         Dim t1 As Task = factory.StartNew(Sub()
                                              For outer As Integer = 0 To 10
                                                 For i As Integer = &h21 To &h7E
                                                    SyncLock objLock
                                                       Console.Write("'{0}' in task t1-{1} on thread {2}   ", 
                                                                     Convert.ToChar(i), iteration, Thread.CurrentThread.ManagedThreadId)
                                                       outputItem += 1
                                                       If outputItem Mod 3 = 0 Then Console.WriteLine()
                                                    End SyncLock 
                                                 Next     
                                              Next                                           
                                           End Sub,
                                cts.Token)           
         tasks.Add(t1)
      Next
      
      ' Wait for the tasks to complete before displaying a completion message.
      Task.WaitAll(tasks.ToArray())
      cts.Dispose()
      Console.WriteLine(vbCrLf + vbCrLf + "Successful completion.")
   End Sub 
End Module

' Provides a task scheduler that ensures a maximum concurrency level while 
' running on top of the thread pool.
Public Class LimitedConcurrencyLevelTaskScheduler : Inherits TaskScheduler
   ' Indicates whether the current thread is processing work items.
   <ThreadStatic()> Private Shared _currentThreadIsProcessingItems As Boolean 
   
   ' The list of tasks to be executed 
   Private ReadOnly _tasks As LinkedList(Of Task) = New LinkedList(Of Task)() 
   
   'The maximum concurrency level allowed by this scheduler. 
   Private ReadOnly _maxDegreeOfParallelism As Integer 
   
   ' Indicates whether the scheduler is currently processing work items. 
   Private _delegatesQueuedOrRunning As Integer = 0 ' protected by lock(_tasks)
   
   ' Creates a new instance with the specified degree of parallelism. 
   Public Sub New(ByVal maxDegreeOfParallelism As Integer)
      If (maxDegreeOfParallelism < 1) Then 
         Throw New ArgumentOutOfRangeException("maxDegreeOfParallelism")
      End If
         _maxDegreeOfParallelism = maxDegreeOfParallelism
   End Sub 

   ' Queues a task to the scheduler. 
   Protected Overrides Sub QueueTask(ByVal t As Task)
      ' Add the task to the list of tasks to be processed.  If there aren't enough 
      ' delegates currently queued or running to process tasks, schedule another. 
      SyncLock (_tasks)
         _tasks.AddLast(t)
         If (_delegatesQueuedOrRunning < _maxDegreeOfParallelism) Then
            _delegatesQueuedOrRunning = _delegatesQueuedOrRunning + 1
            NotifyThreadPoolOfPendingWork()
         End If 
      End SyncLock 
   End Sub 
   
   ' Inform the ThreadPool that there's work to be executed for this scheduler. 
   Private Sub NotifyThreadPoolOfPendingWork()
   
      ThreadPool.UnsafeQueueUserWorkItem(Sub()
                                            ' Note that the current thread is now processing work items. 
                                            ' This is necessary to enable inlining of tasks into this thread.
                                            _currentThreadIsProcessingItems = True 
                                            Try 
                                               ' Process all available items in the queue. 
                                               While (True)
                                                  Dim item As Task
                                                  SyncLock (_tasks)
                                                     ' When there are no more items to be processed, 
                                                     ' note that we're done processing, and get out. 
                                                     If (_tasks.Count = 0) Then
                                                        _delegatesQueuedOrRunning = _delegatesQueuedOrRunning - 1
                                                        Exit While 
                                                     End If 
   
                                                     ' Get the next item from the queue
                                                     item = _tasks.First.Value
                                                     _tasks.RemoveFirst()
                                                  End SyncLock 
   
                                                  ' Execute the task we pulled out of the queue 
                                                  MyBase.TryExecuteTask(item)
                                               End While 
                                               ' We're done processing items on the current thread 
                                            Finally
                                               _currentThreadIsProcessingItems = False 
                                            End Try 
                                         End Sub,
                                    Nothing)
   End Sub 
   
   ' Attempts to execute the specified task on the current thread. 
   Protected Overrides Function TryExecuteTaskInline(ByVal t As Task, 
                                                     ByVal taskWasPreviouslyQueued As Boolean) As Boolean 
      ' If this thread isn't already processing a task, we don't support inlining 
      If (Not _currentThreadIsProcessingItems) Then 
         Return False 
      End If 
   
      ' If the task was previously queued, remove it from the queue 
      If (taskWasPreviouslyQueued) Then
         ' Try to run the task. 
         If TryDequeue(t) Then 
            Return MyBase.TryExecuteTask(t)
         Else
            Return False 
         End If     
      Else 
         Return MyBase.TryExecuteTask(t)
      End If   
   End Function 
   
   ' Attempt to remove a previously scheduled task from the scheduler. 
   Protected Overrides Function TryDequeue(ByVal t As Task) As Boolean 
      SyncLock (_tasks)
         Return _tasks.Remove(t)
      End SyncLock 
   End Function 
   
   ' Gets the maximum concurrency level supported by this scheduler. 
   Public Overrides ReadOnly Property MaximumConcurrencyLevel As Integer 
      Get 
         Return _maxDegreeOfParallelism
      End Get 
   End Property 
   
   ' Gets an enumerable of the tasks currently scheduled on this scheduler. 
   Protected Overrides Function GetScheduledTasks() As IEnumerable(Of Task)
      Dim lockTaken As Boolean = False 
      Try
         Monitor.TryEnter(_tasks, lockTaken)
         If (lockTaken) Then 
            Return _tasks.ToArray()
         Else 
            Throw New NotSupportedException()
         End If 
      Finally 
         If (lockTaken) Then
            Monitor.Exit(_tasks)
         End If 
      End Try 
   End Function 
End Class 
' The following is a portion of the output from a single run of the example:
'    'T' in task t1-4 on thread 3   'U' in task t1-4 on thread 3   'V' in task t1-4 on thread 3   
'    'W' in task t1-4 on thread 3   'X' in task t1-4 on thread 3   'Y' in task t1-4 on thread 3   
'    'Z' in task t1-4 on thread 3   '[' in task t1-4 on thread 3   '\' in task t1-4 on thread 3   
'    ']' in task t1-4 on thread 3   '^' in task t1-4 on thread 3   '_' in task t1-4 on thread 3   
'    '`' in task t1-4 on thread 3   'a' in task t1-4 on thread 3   'b' in task t1-4 on thread 3   
'    'c' in task t1-4 on thread 3   'd' in task t1-4 on thread 3   'e' in task t1-4 on thread 3   
'    'f' in task t1-4 on thread 3   'g' in task t1-4 on thread 3   'h' in task t1-4 on thread 3   
'    'i' in task t1-4 on thread 3   'j' in task t1-4 on thread 3   'k' in task t1-4 on thread 3   
'    'l' in task t1-4 on thread 3   'm' in task t1-4 on thread 3   'n' in task t1-4 on thread 3   
'    'o' in task t1-4 on thread 3   'p' in task t1-4 on thread 3   ']' in task t1-2 on thread 4   
'    '^' in task t1-2 on thread 4   '_' in task t1-2 on thread 4   '`' in task t1-2 on thread 4   
'    'a' in task t1-2 on thread 4   'b' in task t1-2 on thread 4   'c' in task t1-2 on thread 4   
'    'd' in task t1-2 on thread 4   'e' in task t1-2 on thread 4   'f' in task t1-2 on thread 4   
'    'g' in task t1-2 on thread 4   'h' in task t1-2 on thread 4   'i' in task t1-2 on thread 4   
'    'j' in task t1-2 on thread 4   'k' in task t1-2 on thread 4   'l' in task t1-2 on thread 4   
'    'm' in task t1-2 on thread 4   'n' in task t1-2 on thread 4   'o' in task t1-2 on thread 4   
'    'p' in task t1-2 on thread 4   'q' in task t1-2 on thread 4   'r' in task t1-2 on thread 4   
'    's' in task t1-2 on thread 4   't' in task t1-2 on thread 4   'u' in task t1-2 on thread 4   
'    'v' in task t1-2 on thread 4   'w' in task t1-2 on thread 4   'x' in task t1-2 on thread 4   
'    'y' in task t1-2 on thread 4   'z' in task t1-2 on thread 4   '{' in task t1-2 on thread 4   
'    '|' in task t1-2 on thread 4   '}' in task t1-2 on thread 4   '~' in task t1-2 on thread 4   
'    'q' in task t1-4 on thread 3   'r' in task t1-4 on thread 3   's' in task t1-4 on thread 3   
'    't' in task t1-4 on thread 3   'u' in task t1-4 on thread 3   'v' in task t1-4 on thread 3   
'    'w' in task t1-4 on thread 3   'x' in task t1-4 on thread 3   'y' in task t1-4 on thread 3   
'    'z' in task t1-4 on thread 3   '{' in task t1-4 on thread 3   '|' in task t1-4 on thread 3  

Außerdem sind mehrere Beispiel Aufgabenplaner in der Code Galerie verfügbar: Beispiele für die parallele Programmierung mit dem .NET Framework 4.In addition, several sample task schedulers are available on Code Gallery: Samples for Parallel Programming with the .NET Framework 4.

Hinweise

Eine Instanz der TaskScheduler -Klasse stellt einen Aufgabenplaner dar.An instance of the TaskScheduler class represents a task scheduler. Durch einen Aufgabenplaner wird sichergestellt, dass die Arbeit einer Aufgabe schließlich ausgeführt wird.A task scheduler ensures that the work of a task is eventually executed.

Der standardmäßige Taskplaner basiert auf dem .NET Framework 4-Threadpool, der Arbeitsübernahme für Lastenausgleich und Threadeinfügung/-deaktivierung für maximalen Durchsatz ermöglicht und für eine gute Gesamtleistung sorgt.The default task scheduler is based on the .NET Framework 4 thread pool, which provides work-stealing for load-balancing, thread injection/retirement for maximum throughput, and overall good performance. Dies ist für die meisten Szenarien in der Regel ausreichend.It should be sufficient for most scenarios.

Die TaskScheduler -Klasse dient auch als Erweiterungs Punkt für alle anpassbaren Planungslogik.The TaskScheduler class also serves as the extension point for all customizable scheduling logic. Dies schließt Mechanismen ein, z. b. das Planen einer Aufgabe für die Ausführung und die Art und Weise, wie geplante Aufgaben für debuggger verfügbar gemacht werden sollen.This includes mechanisms such as how to schedule a task for execution, and how scheduled tasks should be exposed to debuggers. Wenn Sie spezielle Funktionen benötigen, können Sie einen benutzerdefinierten Planer erstellen und für bestimmte Tasks oder Abfragen aktivieren.If you require special functionality, you can create a custom scheduler and enable it for specific tasks or queries.

In diesem Thema:In this topic:
Der Standardaufgaben Planer und der Thread PoolThe default task scheduler and the thread pool
Die globale Warteschlange im Vergleich zu lokalen WarteschlangenThe global queue vs. local queues
Arbeits DiebstahlWork stealing
Aufgaben mit langer AusführungszeitLong-running tasks
Task InliningTask inlining
Angeben eines Synchronisierungs KontextsSpecifying a synchronization context

Der Standardaufgaben Planer und der Thread PoolThe default task scheduler and the thread pool

Der Standard Planer für die Task Parallel Library und PLINQ verwendet den .NET Framework Thread Pool, der durch die ThreadPool -Klasse dargestellt wird, um die Arbeit in die Warteschlange zu stellen und auszuführen.The default scheduler for the Task Parallel Library and PLINQ uses the .NET Framework thread pool, which is represented by the ThreadPool class, to queue and execute work. Der Thread Pool verwendet die Informationen, die vom Task -Typ bereitgestellt werden, um die differenzierte Parallelität (kurzlebige Arbeitseinheiten) effizient zu unterstützen, die parallele Tasks und Abfragen häufig darstellen.The thread pool uses the information that is provided by the Task type to efficiently support the fine-grained parallelism (short-lived units of work) that parallel tasks and queries often represent.

Die globale Warteschlange im Vergleich zu lokalen WarteschlangenThe global queue vs. local queues

Der Thread Pool verwaltet eine globale FIFO-Arbeits Warteschlange (First in, First Out) für Threads in jeder Anwendungsdomäne.The thread pool maintains a global FIFO (first-in, first-out) work queue for threads in each application domain. Wenn ein Programm die ThreadPool.QueueUserWorkItem Methode (oder ThreadPool.UnsafeQueueUserWorkItem) aufruft, wird die Arbeit in diese freigegebene Warteschlange eingereiht und schließlich auf den nächsten Thread, der verfügbar wird, deaktiviert.Whenever a program calls the ThreadPool.QueueUserWorkItem (or ThreadPool.UnsafeQueueUserWorkItem) method, the work is put on this shared queue and eventually de-queued onto the next thread that becomes available. Beginnend mit der .NET Framework 4 wurde diese Warteschlange verbessert, um einen Sperr freien Algorithmus zu verwenden, der der ConcurrentQueue<T> -Klasse ähnelt.Starting with the .NET Framework 4, this queue has been improved to use a lock-free algorithm that resembles the ConcurrentQueue<T> class. Mit dieser sperrenfreien Implementierung verbringt der Thread Pool weniger Zeit, wenn Arbeitselemente in die Warteschlange eingereiht und aus der Warteschlange entfernt werden.By using this lock-free implementation, the thread pool spends less time when it queues and de-queues work items. Dieser Leistungsvorteil ist für alle Programme verfügbar, die den Thread Pool verwenden.This performance benefit is available to all programs that use the thread pool.

Aufgaben der obersten Ebene, bei denen es sich um Aufgaben handelt, die nicht im Kontext einer anderen Aufgabe erstellt werden, werden wie jedes andere Arbeitselement in der globalen Warteschlange abgelegt.Top-level tasks, which are tasks that are not created in the context of another task, are put on the global queue just like any other work item. Geschachtelte oder untergeordnete Aufgaben, die im Kontext einer anderen Aufgabe erstellt werden, werden hingegen anders behandelt.However, nested or child tasks, which are created in the context of another task, are handled quite differently. Ein untergeordnetes Element oder eine geschachtelte Aufgabe wird in einer lokalen Warteschlange abgelegt, die speziell für den Thread vorgesehen ist, in dem die übergeordnete Aufgabe ausgeführt wird.A child or nested task is put on a local queue that is specific to the thread on which the parent task is executing. Die übergeordnete Aufgabe ist möglicherweise eine Aufgabe der obersten Ebene. Es kann sich jedoch auch um das untergeordnete Element einer anderen Aufgabe handeln.The parent task may be a top-level task or it also may be the child of another task. Wenn dieser Thread für weitere Arbeitsvorgänge bereit ist, wird zuerst eine Suche in der lokalen Warteschlange ausgeführt.When this thread is ready for more work, it first looks in the local queue. Wenn darin Arbeitselemente warten, kann darauf schnell zugegriffen werden.If work items are waiting there, they can be accessed quickly. Auf die lokalen Warteschlangen wird in der Last-in-First-Out-Reihenfolge (LIFO) zugegriffen, um die Cache Lokalität beizubehalten und Konflikte zu verringern.The local queues are accessed in last-in, first-out order (LIFO) to preserve cache locality and reduce contention. Weitere Informationen zu untergeordneten und untergeordneten Aufgaben finden Sie unter angefügte und getrennteuntergeordnete Aufgaben.For more information about child tasks and nested tasks, see Attached and Detached Child Tasks.

Durch die Verwendung lokaler Warteschlangen wird nicht nur der Druck der globalen Warteschlange verringert, sondern auch die Daten Lokalität genutzt.The use of local queues not only reduces pressure on the global queue, but also takes advantage of data locality. Arbeitselemente in der lokalen Warteschlange verweisen häufig auf Datenstrukturen, die im Arbeitsspeicher physisch nahe beieinander liegen.Work items in the local queue frequently reference data structures that are physically near one another in memory. In diesen Fällen befinden sich die Daten bereits im Cache, nachdem die erste Aufgabe ausgeführt wurde und schnell auf Sie zugegriffen werden kann.In these cases, the data is already in the cache after the first task has run and can be accessed quickly. Sowohl parallele LINQ (PLINQ) als auch Parallel die-Klasse verwenden in großem Umfang geschachtelte Tasks und untergeordnete Aufgaben und erzielen mithilfe der lokalen Arbeits Warteschlangen deutliche Beschleunigung.Both Parallel LINQ (PLINQ) and the Parallel class use nested tasks and child tasks extensively, and achieve significant speedups by using the local work queues.

Arbeits DiebstahlWork stealing

Beginnend mit dem .NET Framework 4 verfügt der Thread Pool auch über einen Arbeits Übernahme-Algorithmus, um sicherzustellen, dass sich keine Threads im Leerlauf befinden, während andere weiterhin in ihren Warteschlangen arbeiten.Starting with the .NET Framework 4, the thread pool also features a work-stealing algorithm to help make sure that no threads are sitting idle while others still have work in their queues. Wenn ein Threadpoolthread zusätzliche Arbeit übernehmen kann, wird zuerst am Anfang der lokalen Warteschlange, anschließend in der globalen Warteschlange und zuletzt in den lokalen Warteschlangen anderer Threads gesucht.When a thread-pool thread is ready for more work, it first looks at the head of its local queue, then in the global queue, and then in the local queues of other threads. Wenn ein Arbeitselement in der lokalen Warteschlange eines anderen Threads gefunden wird, wird zunächst Heuristik angewendet, um sicherzustellen, dass die Arbeit effizient ausgeführt werden kann.If it finds a work item in the local queue of another thread, it first applies heuristics to make sure that it can run the work efficiently. Wenn dies der Fall ist, wird das Arbeits Element aus der Warteschlange entfernt (in FIFO-Reihenfolge).If it can, it de-queues the work item from the tail (in FIFO order). Dadurch werden Konflikte in jeder lokalen Warteschlange verringert und der Datenort beibehalten.This reduces contention on each local queue and preserves data locality. Diese Architektur unterstützt den Thread Pool-Lastenausgleich effizienter als in früheren Versionen.This architecture helps the thread pool load-balance work more efficiently than past versions did.

Aufgaben mit langer AusführungszeitLong-running tasks

Unter Umständen möchten Sie ausdrücklich verhindern, dass eine Aufgabe in einer lokalen Warteschlange abgelegt wird.You may want to explicitly prevent a task from being put on a local queue. Sie wissen möglicherweise z. B., dass eine bestimmte Arbeitsaufgabe für eine relativ lange Zeit ausgeführt wird und daher wahrscheinlich alle anderen Arbeitsaufgaben in der lokalen Warteschlange blockiert.For example, you may know that a particular work item will run for a relatively long time and is likely to block all other work items on the local queue. In diesem Fall können Sie die System.Threading.Tasks.TaskCreationOptions-Option angeben, die den Planer darauf hinweist, dass u. U. ein weiterer Thread für die Aufgabe erforderlich ist, damit der Fortschritt anderer Threads oder Arbeitsaufgaben in der lokalen Warteschlange nicht blockiert wird.In this case, you can specify the System.Threading.Tasks.TaskCreationOptions option, which provides a hint to the scheduler that an additional thread might be required for the task so that it does not block the forward progress of other threads or work items on the local queue. Mit dieser Option vermeiden Sie den Thread Pool vollständig, einschließlich der globalen und lokalen Warteschlangen.By using this option you avoid the thread pool completely, including the global and local queues.

Task InliningTask inlining

In einigen Fällen, in Task denen ein gewartet wird, wird es möglicherweise synchron in dem Thread ausgeführt, der den warte Vorgang ausführt.In some cases when a Task is waited on, it may be executed synchronously on the thread that is performing the wait operation. Dadurch wird die Leistung verbessert, da ein zusätzlicher Thread nicht mehr benötigt wird und stattdessen der vorhandene Thread verwendet wird, der andernfalls blockiert wäre.This enhances performance by preventing the need for an additional thread and instead using the existing thread, which would have blocked otherwise. Um Fehler aufgrund eines erneuten Eintretens zu vermeiden, tritt das Inlining der Aufgabe nur auf, wenn das warte Ziel in der lokalen Warteschlange des relevanten Threads gefunden wird.To prevent errors due to reentrancy, task inlining only occurs when the wait target is found in the relevant thread's local queue.

Angeben eines Synchronisierungs KontextsSpecifying a synchronization context

Sie können mit der TaskScheduler.FromCurrentSynchronizationContext-Methode angeben, dass eine Aufgabe für die Ausführung in einem bestimmten Thread geplant werden soll.You can use the TaskScheduler.FromCurrentSynchronizationContext method to specify that a task should be scheduled to run on a particular thread. Dies ist in Frameworks wie Windows Forms und Windows Presentation Foundation hilfreich, wo der Zugriff auf Benutzeroberflächenobjekte oftmals auf Code beschränkt ist, der in dem Thread ausgeführt wird, in dem das Benutzeroberflächenobjekt erstellt wurde.This is useful in frameworks such as Windows Forms and Windows Presentation Foundation where access to user interface objects is often restricted to code that is running on the same thread on which the UI object was created.

Im folgenden Beispiel wird die TaskScheduler.FromCurrentSynchronizationContext -Methode in einer Windows Presentation Foundation-app (WPF) verwendet, um eine Aufgabe im gleichen Thread zu planen, in dem auch das Steuerelement der Benutzeroberfläche erstellt wurde.The following example uses the TaskScheduler.FromCurrentSynchronizationContext method in a Windows Presentation Foundation (WPF) app to schedule a task on the same thread that the user interface (UI) control was created on. Im Beispiel wird ein Mosaik von Bildern erstellt, die nach dem Zufallsprinzip aus einem angegebenen Verzeichnis ausgewählt werden.The example creates a mosaic of images that are randomly selected from a specified directory. Die WPF-Objekte werden verwendet, um die Bilder zu laden und zu ändern.The WPF objects are used to load and resize the images. Die Rohdaten werden dann an eine Aufgabe weitergegeben, die For eine-Schleife verwendet, um die Pixeldaten in ein großes Einzel Byte Array zu schreiben.The raw pixels are then passed to a task that uses a For loop to write the pixel data into a large single-byte array. Es ist keine Synchronisierung erforderlich, da keine zwei Kacheln dieselben Array Elemente belegen.No synchronization is required because no two tiles occupy the same array elements. Die Kacheln können auch in beliebiger Reihenfolge geschrieben werden, da ihre Position unabhängig von einer anderen Kachel berechnet wird.The tiles can also be written in any order because their position is calculated independently of any other tile. Das große Array wird dann an einen Task weitergeleitet, der im UI-Thread ausgeführt wird, in dem die Pixeldaten in ein Bild Steuerelement geladen werden.The large array is then passed to a task that runs on the UI thread, where the pixel data is loaded into an Image control.

Im Beispiel werden Daten aus dem UI-Thread verschoben, mithilfe paralleler Schleifen und Objekten Task geändert und dann wieder an eine Aufgabe weitergeleitet, die im UI-Thread ausgeführt wird.The example moves data off the UI thread, modifies it by using parallel loops and Task objects, and then passes it back to a task that runs on the UI thread. Diese Vorgehensweise ist nützlich, wenn Sie die Task Parallel Library zum Durchführen von Vorgängen verwenden müssen, die von der WPF-API nicht unterstützt werden oder nicht ausreichend schnell sind.This approach is useful when you have to use the Task Parallel Library to perform operations that either are not supported by the WPF API, or are not sufficiently fast. Eine weitere Möglichkeit zum Erstellen eines Bild Mosaiks in WPF ist die System.Windows.Controls.WrapPanel Verwendung eines Steuer Elements und das Hinzufügen von Bildern.Another way to create an image mosaic in WPF is to use a System.Windows.Controls.WrapPanel control and add images to it. Der WrapPanel übernimmt das Positionieren der Kacheln.The WrapPanel handles the work of positioning the tiles. Diese Arbeit kann jedoch nur im UI-Thread ausgeführt werden.However, this work can only be performed on the UI thread.

using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace WPF_CS1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private int fileCount;
        int colCount;
        int rowCount;
        private int tilePixelHeight;
        private int tilePixelWidth;
        private int largeImagePixelHeight;
        private int largeImagePixelWidth;
        private int largeImageStride;
        PixelFormat format;
        BitmapPalette palette = null;

        public MainWindow()
        {
            InitializeComponent();

            // For this example, values are hard-coded to a mosaic of 8x8 tiles.
            // Each tile is 50 pixels high and 66 pixels wide and 32 bits per pixel.
            colCount = 12;
            rowCount = 8;
            tilePixelHeight = 50;
            tilePixelWidth = 66;
            largeImagePixelHeight = tilePixelHeight * rowCount;
            largeImagePixelWidth = tilePixelWidth * colCount;
            largeImageStride = largeImagePixelWidth * (32 / 8);
            this.Width = largeImagePixelWidth + 40;
            image.Width = largeImagePixelWidth;
            image.Height = largeImagePixelHeight;


        }

        private void button_Click(object sender, RoutedEventArgs e)
        {

            // For best results use 1024 x 768 jpg files at 32bpp.
            string[] files = System.IO.Directory.GetFiles(@"C:\Users\Public\Pictures\Sample Pictures\", "*.jpg");

            fileCount = files.Length;
            Task<byte[]>[] images = new Task<byte[]>[fileCount];
            for (int i = 0; i < fileCount; i++)
            {
                int x = i;
                images[x] = Task.Factory.StartNew(() => LoadImage(files[x]));
            }

            // When they've all been loaded, tile them into a single byte array.
            var tiledImage = Task.Factory.ContinueWhenAll(
                images, (i) => TileImages(i));

            // We are currently on the UI thread. Save the sync context and pass it to
            // the next task so that it can access the UI control "image".
            var UISyncContext = TaskScheduler.FromCurrentSynchronizationContext();

            // On the UI thread, put the bytes into a bitmap and
            // display it in the Image control.
            var t3 = tiledImage.ContinueWith((antecedent) =>
            {
                // Get System DPI.
                Matrix m = PresentationSource.FromVisual(Application.Current.MainWindow)
                                            .CompositionTarget.TransformToDevice;
                double dpiX = m.M11;
                double dpiY = m.M22;

                BitmapSource bms = BitmapSource.Create(largeImagePixelWidth,
                    largeImagePixelHeight,
                    dpiX,
                    dpiY,
                    format,
                    palette, //use default palette
                    antecedent.Result,
                    largeImageStride);
                image.Source = bms;
            }, UISyncContext);
        }

        byte[] LoadImage(string filename)
        {
            // Use the WPF BitmapImage class to load and 
            // resize the bitmap. NOTE: Only 32bpp formats are supported correctly.
            // Support for additional color formats is left as an exercise
            // for the reader. For more information, see documentation for ColorConvertedBitmap.

            BitmapImage bitmapImage = new BitmapImage();
            bitmapImage.BeginInit();
            bitmapImage.UriSource = new Uri(filename);
            bitmapImage.DecodePixelHeight = tilePixelHeight;
            bitmapImage.DecodePixelWidth = tilePixelWidth;
            bitmapImage.EndInit();

            format = bitmapImage.Format;
            int size = (int)(bitmapImage.Height * bitmapImage.Width);
            int stride = (int)bitmapImage.Width * 4;
            byte[] dest = new byte[stride * tilePixelHeight];

            bitmapImage.CopyPixels(dest, stride, 0);

            return dest;
        }

        int Stride(int pixelWidth, int bitsPerPixel)
        {
            return (((pixelWidth * bitsPerPixel + 31) / 32) * 4);
        }

        // Map the individual image tiles to the large image
        // in parallel. Any kind of raw image manipulation can be
        // done here because we are not attempting to access any 
        // WPF controls from multiple threads.
        byte[] TileImages(Task<byte[]>[] sourceImages)
        {
            byte[] largeImage = new byte[largeImagePixelHeight * largeImageStride];
            int tileImageStride = tilePixelWidth * 4; // hard coded to 32bpp

            Random rand = new Random();
            Parallel.For(0, rowCount * colCount, (i) =>
            {
                // Pick one of the images at random for this tile.
                int cur = rand.Next(0, sourceImages.Length);
                byte[] pixels = sourceImages[cur].Result;

                // Get the starting index for this tile.
                int row = i / colCount;
                int col = (int)(i % colCount);
                int idx = ((row * (largeImageStride * tilePixelHeight)) + (col * tileImageStride));

                // Write the pixels for the current tile. The pixels are not contiguous
                // in the array, therefore we have to advance the index by the image stride
                // (minus the stride of the tile) for each scanline of the tile.
                int tileImageIndex = 0;
                for (int j = 0; j < tilePixelHeight; j++)
                {
                    // Write the next scanline for this tile.
                    for (int k = 0; k < tileImageStride; k++)
                    {
                        largeImage[idx++] = pixels[tileImageIndex++];
                    }
                    // Advance to the beginning of the next scanline.
                    idx += largeImageStride - tileImageStride;
                }
            });
            return largeImage;
        }
    }
}
Imports System.Threading.Tasks
Imports System.Windows
Imports System.Windows.Media
Imports System.Windows.Media.Imaging

Partial Public Class MainWindow : Inherits Window
    Dim fileCount As Integer
    Dim colCount As Integer
    Dim rowCount As Integer
    Dim tilePixelHeight As Integer
    Dim tilePixelWidth As Integer
    Dim largeImagePixelHeight As Integer
    Dim largeImagePixelWidth As Integer
    Dim largeImageStride As Integer
    Dim format As PixelFormat
    Dim palette As BitmapPalette = Nothing

    Public Sub New()
        InitializeComponent()

        ' For this example, values are hard-coded to a mosaic of 8x8 tiles.
        ' Each tile Is 50 pixels high and 66 pixels wide and 32 bits per pixel.
        colCount = 12
        rowCount = 8
        tilePixelHeight = 50
        tilePixelWidth = 66
        largeImagePixelHeight = tilePixelHeight * rowCount
        largeImagePixelWidth = tilePixelWidth * colCount
        largeImageStride = largeImagePixelWidth * (32 / 8)
        Me.Width = largeImagePixelWidth + 40
        image.Width = largeImagePixelWidth
        image.Height = largeImagePixelHeight
    End Sub

    Private Sub button_Click(sender As Object, e As RoutedEventArgs) _
        Handles button.Click

        ' For best results use 1024 x 768 jpg files at 32bpp.
        Dim files() As String = System.IO.Directory.GetFiles("C:\Users\Public\Pictures\Sample Pictures\", "*.jpg")

        fileCount = files.Length
        Dim images(fileCount - 1) As Task(Of Byte())
        For i As Integer = 0 To fileCount - 1
            Dim x As Integer = i
            images(x) = Task.Factory.StartNew(Function() LoadImage(files(x)))
        Next

        ' When they have all been loaded, tile them into a single byte array.
        'var tiledImage = Task.Factory.ContinueWhenAll(
        '        images, (i) >= TileImages(i));

        '        Dim tiledImage As Task(Of Byte()) = Task.Factory.ContinueWhenAll(images, Function(i As Task(Of Byte())) TileImages(i))
        Dim tiledImage = Task.Factory.ContinueWhenAll(images, Function(i As Task(Of Byte())()) TileImages(i))
        ' We are currently on the UI thread. Save the sync context and pass it to
        ' the next task so that it can access the UI control "image1".
        Dim UISyncContext = TaskScheduler.FromCurrentSynchronizationContext()

        ' On the UI thread, put the bytes into a bitmap and
        ' display it in the Image control.
        Dim t3 = tiledImage.ContinueWith(Sub(antecedent)
                                             ' Get System DPI.
                                             Dim m As Matrix = PresentationSource.FromVisual(Application.Current.MainWindow).CompositionTarget.TransformToDevice
                                             Dim dpiX As Double = m.M11
                                             Dim dpiY As Double = m.M22

                                             ' Use the default palette in creating the bitmap.
                                             Dim bms As BitmapSource = BitmapSource.Create(largeImagePixelWidth,
                                                                                           largeImagePixelHeight,
                                             dpiX,
                                             dpiY,
                                             format,
                                             palette,
                                             antecedent.Result,
                                             largeImageStride)
                                             image.Source = bms
                                         End Sub, UISyncContext)
    End Sub

    Public Function LoadImage(filename As String) As Byte()
        ' Use the WPF BitmapImage class to load and 
        ' resize the bitmap. NOTE: Only 32bpp formats are supported correctly.
        ' Support for additional color formats Is left as an exercise
        ' for the reader. For more information, see documentation for ColorConvertedBitmap.
        Dim bitmapImage As New BitmapImage()
        bitmapImage.BeginInit()
        bitmapImage.UriSource = New Uri(filename)
        bitmapImage.DecodePixelHeight = tilePixelHeight
        bitmapImage.DecodePixelWidth = tilePixelWidth
        bitmapImage.EndInit()

        format = bitmapImage.Format
        Dim size As Integer = CInt(bitmapImage.Height * bitmapImage.Width)
        Dim stride As Integer = CInt(bitmapImage.Width * 4)
        Dim dest(stride * tilePixelHeight - 1) As Byte

        bitmapImage.CopyPixels(dest, stride, 0)

        Return dest
    End Function

    Function Stride(pixelWidth As Integer, bitsPerPixel As Integer) As Integer
        Return (((pixelWidth * bitsPerPixel + 31) / 32) * 4)
    End Function

    ' Map the individual image tiles to the large image
    ' in parallel. Any kind of raw image manipulation can be
    ' done here because we are Not attempting to access any 
    ' WPF controls from multiple threads.
    Function TileImages(sourceImages As Task(Of Byte())()) As Byte()
        Dim largeImage(largeImagePixelHeight * largeImageStride - 1) As Byte
        Dim tileImageStride As Integer = tilePixelWidth * 4 ' hard coded To 32bpp

        Dim rand As New Random()
        Parallel.For(0, rowCount * colCount, Sub(i)
                                                 ' Pick one of the images at random for this tile.
                                                 Dim cur As Integer = rand.Next(0, sourceImages.Length)
                                                 Dim pixels() As Byte = sourceImages(cur).Result

                                                 ' Get the starting index for this tile.
                                                 Dim row As Integer = i \ colCount
                                                 Dim col As Integer = i Mod colCount
                                                 Dim idx As Integer = ((row * (largeImageStride * tilePixelHeight)) + (col * tileImageStride))

                                                 ' Write the pixels for the current tile. The pixels are Not contiguous
                                                 ' in the array, therefore we have to advance the index by the image stride
                                                 ' (minus the stride of the tile) for each scanline of the tile.
                                                 Dim tileImageIndex As Integer = 0
                                                 For j As Integer = 0 To tilePixelHeight - 1
                                                     ' Write the next scanline for this tile.
                                                     For k As Integer = 0 To tileImageStride - 1
                                                         largeImage(idx) = pixels(tileImageIndex)
                                                         idx += 1
                                                         tileImageIndex += 1
                                                     Next
                                                     ' Advance to the beginning of the next scanline.
                                                     idx += largeImageStride - tileImageStride
                                                 Next
                                             End Sub)
        Return largeImage
    End Function
End Class

Um das Beispiel zu erstellen, erstellen Sie in Visual Studio ein WPF-Anwendungsprojekt, und nennen Sie C# es WPF_CS1 (für ein WPF-Projekt) oder WPF_VB1 (für ein Visual Basic WPF-Projekt).To create the example, create a WPF application project in Visual Studio and name it WPF_CS1 (for a C# WPF project) or WPF_VB1 (for a Visual Basic WPF project). Gehen Sie dann wie folgt vor:Then do the following:

  1. Ziehen Sie in der Entwurfs Ansicht Image ein-Steuerelement aus der Toolbox auf die linke obere Ecke der Entwurfs Oberfläche.In design view, drag an Image control from the Toolbox onto the upper left corner of the design surface. Benennen Sie das Steuerelement im Textfeld Name des Fensters Eigenschaften mit dem Namen "Image".In the Name textbox of the Properties window, name the control "image".

  2. Ziehen Sie Button ein-Steuerelement aus der Toolbox in den unteren linken Bereich des Anwendungsfensters.Drag a Button control from the Toolbox to the lower left part of the application window. Geben Sie in der XAML- Content Ansicht die-Eigenschaft der Schaltfläche als "Make a Mosaic" an Width , und geben Sie die zugehörige-Eigenschaft als "100" an.In XAML view, specify the Content property of the button as "Make a mosaic", and specify its Width property as "100". Verbinden Sie Click das Ereignis mit button_Click dem Ereignishandler, der im Code des Beispiels definiert Click="button_Click" ist, <Button> indem Sie dem-Element hinzufügen.Connect the Click event with the button_Click event handler defined in the example's code by adding Click="button_Click" to the <Button> element. Benennen Sie das Steuerelement im Textfeld Name des Fensters Eigenschaften mit "Schaltfläche".In the Name textbox of the Properties window, name the control "button".

  3. Ersetzen Sie den gesamten Inhalt der MainWindow.XAML.cs-oder MainWindow. XAML. vb-Datei durch den Code aus diesem Beispiel.Replace the entire contents of the MainWindow.xaml.cs or MainWindow.xaml.vb file with the code from this example. Stellen Sie C# bei einem WPF-Projekt sicher, dass der Name des Arbeitsbereichs mit dem Projektnamen übereinstimmt.For a C# WPF project, make sure that the name of the workspace matches the project name.

  4. Im Beispiel werden JPEG-Bilder aus einem Verzeichnis namens "c:\Users\Public\Pictures\Sample Pictures\" gelesen.The example reads JPEG images from a directory named C:\Users\Public\Pictures\Sample Pictures\. Erstellen Sie das Verzeichnis, und platzieren Sie einige Bilder, oder ändern Sie den Pfad so, dass er auf ein anderes Verzeichnis verweist, das Bilder enthält.Either create the directory and place some images in it, or change the path to refer to some other directory that contains images.

In diesem Beispiel sind einige Einschränkungen zu beachten.This example has some limitations. Beispielsweise werden nur 32 Bits pro Pixel-Bilder unterstützt. Bilder in anderen Formaten werden durch das BitmapImage -Objekt während der Änderung der Größe beschädigt.For example, only 32-bits-per-pixel images are supported; images in other formats are corrupted by the BitmapImage object during the resizing operation. Außerdem müssen die Quell Images alle größer als die Kachel Größe sein.Also, the source images must all be larger than the tile size. Als weitere Übung können Sie Funktionen hinzufügen, mit denen mehrere Pixel Formate und Dateigrößen behandelt werden.As a further exercise, you can add functionality to handle multiple pixel formats and file sizes.

Konstruktoren

TaskScheduler() TaskScheduler() TaskScheduler() TaskScheduler()

Initialisiert das TaskScheduler.Initializes the TaskScheduler.

Eigenschaften

Current Current Current Current

Ruft den zugeordneten TaskScheduler der derzeit ausgeführten Aufgabe ab.Gets the TaskScheduler associated with the currently executing task.

Default Default Default Default

Ruft die TaskScheduler-Standardinstanz ab, die von .NET Framework bereitgestellt wird.Gets the default TaskScheduler instance that is provided by the .NET Framework.

Id Id Id Id

Ruft die eindeutige ID für diesen TaskScheduler ab.Gets the unique ID for this TaskScheduler.

MaximumConcurrencyLevel MaximumConcurrencyLevel MaximumConcurrencyLevel MaximumConcurrencyLevel

Gibt die maximale Parallelitätsebene an, die dieser TaskScheduler unterstützt.Indicates the maximum concurrency level this TaskScheduler is able to support.

Methoden

Equals(Object) Equals(Object) Equals(Object) Equals(Object)

Bestimmt, ob das angegebene Objekt mit dem aktuellen Objekt identisch ist.Determines whether the specified object is equal to the current object.

(Inherited from Object)
Finalize() Finalize() Finalize() Finalize()

Gibt alle Ressourcen frei, die diesem Planer zugeordnet sind.Frees all resources associated with this scheduler.

FromCurrentSynchronizationContext() FromCurrentSynchronizationContext() FromCurrentSynchronizationContext() FromCurrentSynchronizationContext()

Erstellt einen TaskScheduler, der dem aktuellen SynchronizationContext zugeordnet ist.Creates a TaskScheduler associated with the current SynchronizationContext.

GetHashCode() GetHashCode() GetHashCode() GetHashCode()

Fungiert als Standardhashfunktion.Serves as the default hash function.

(Inherited from Object)
GetScheduledTasks() GetScheduledTasks() GetScheduledTasks() GetScheduledTasks()

Nur für Debuggerunterstützung: Generiert eine Enumeration von Task-Instanzen, die sich gegenwärtig in der Warteschlange des Taskplaners befinden und auf ihre Ausführung warten.For debugger support only, generates an enumerable of Task instances currently queued to the scheduler waiting to be executed.

GetType() GetType() GetType() GetType()

Ruft den Type der aktuellen Instanz ab.Gets the Type of the current instance.

(Inherited from Object)
MemberwiseClone() MemberwiseClone() MemberwiseClone() MemberwiseClone()

Erstellt eine flache Kopie des aktuellen Object.Creates a shallow copy of the current Object.

(Inherited from Object)
QueueTask(Task) QueueTask(Task) QueueTask(Task) QueueTask(Task)

Fügt einen Task in die Warteschlange des Planers ein.Queues a Task to the scheduler.

ToString() ToString() ToString() ToString()

Gibt eine Zeichenfolge zurück, die das aktuelle Objekt darstellt.Returns a string that represents the current object.

(Inherited from Object)
TryDequeue(Task) TryDequeue(Task) TryDequeue(Task) TryDequeue(Task)

Versucht, einen zuvor in die Warteschlange dieses Planers eingereihten Task aus der Warteschlange zu entfernen.Attempts to dequeue a Task that was previously queued to this scheduler.

TryExecuteTask(Task) TryExecuteTask(Task) TryExecuteTask(Task) TryExecuteTask(Task)

Versucht, den angegebenen Task mit diesem Planer auszuführen.Attempts to execute the provided Task on this scheduler.

TryExecuteTaskInline(Task, Boolean) TryExecuteTaskInline(Task, Boolean) TryExecuteTaskInline(Task, Boolean) TryExecuteTaskInline(Task, Boolean)

Bestimmt, ob der angegebene Task in diesem Aufruf synchron ausgeführt werden kann, und führt ihn aus, wenn dies der Fall ist.Determines whether the provided Task can be executed synchronously in this call, and if it can, executes it.

Ereignisse

UnobservedTaskException UnobservedTaskException UnobservedTaskException UnobservedTaskException

Tritt auf, kurz bevor eine nicht überwachte Ausnahme eines Tasks, bei dem ein Fehler aufgetreten ist, eine Ausnahmeausweitungsrichtlinie auslöst, was standardmäßig den Prozess beenden würde.Occurs when a faulted task's unobserved exception is about to trigger exception escalation policy, which, by default, would terminate the process.

Gilt für:

Threadsicherheit

Alle Member des abstrakten TaskScheduler Typs sind Thread sicher und können von mehreren Threads gleichzeitig verwendet werden.All members of the abstract TaskScheduler type are thread-safe and may be used from multiple threads concurrently.

Siehe auch