TaskScheduler Třída
Definice
Důležité
Některé informace platí pro předběžně vydaný produkt, který se může zásadně změnit, než ho výrobce nebo autor vydá. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Představuje objekt, který zpracovává práci nízké úrovně úlohy řazení do fronty na vlákna.
public ref class TaskScheduler abstract
public abstract class TaskScheduler
type TaskScheduler = class
Public MustInherit Class TaskScheduler
- Dědičnost
-
TaskScheduler
Příklady
Následující příklad vytvoří vlastní plánovač úloh, který omezuje počet vláken používaných aplikací. Potom spustí dvě sady úloh a zobrazí informace o úkolu a vlákně, na kterém se úloha spouští.
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
Poznámky
Třída TaskScheduler představuje plánovač úloh. Plánovač úkolů zajistí, že se nakonec spustí práce úkolu.
Výchozí plánovač úloh poskytuje přebírání úloh pro vyrovnávání zatížení, injekce a ukončování vláken pro maximální propustnost a celkově dobrý výkon. Pro většinu scénářů by mělo být dostatečné.
Třída TaskScheduler také slouží jako bod rozšíření pro veškerou přizpůsobitelnou logiku plánování. To zahrnuje mechanismy, jako je naplánování úlohy pro provádění a jak by měly být naplánované úlohy zpřístupněny ladicím programům. Pokud potřebujete speciální funkce, můžete vytvořit vlastní plánovač a povolit ho pro konkrétní úlohy nebo dotazy.
Výchozí plánovač úloh a fond vláken
Výchozí plánovač pro knihovnu Task Parallel Library a PLINQ používá fond vláken .NET, který je reprezentován třídou ThreadPool, za účelem zařazení a spuštění práce. Fond vláken používá informace poskytované typem Task k efektivní podpoře jemně odstupňovaného paralelismu (krátkodobé jednotky práce), které často představují paralelní úlohy a dotazy.
Globální fronta vs. místní fronty
Fond vláken udržuje globální pracovní frontu FIFO (first-in, first-out) pro vlákna v každé doméně aplikace. Kdykoli program zavolá metodu ThreadPool.QueueUserWorkItem (nebo ThreadPool.UnsafeQueueUserWorkItem), práce se umístí do této sdílené fronty a nakonec je vyjmuta z fronty a přidělena dalšímu dostupnému vláknu. Počínaje .NET Frameworkem verze 4 používá tato fronta algoritmus bez použití zámku, který se podobá třídě ConcurrentQueue<T>. Díky použití této implementace bez uzamčení vláknový fond stráví méně času, když zařazuje do fronty a vyřazuje z fronty pracovní položky. Tato výhoda výkonu je k dispozici pro všechny programy, které používají fond vláken.
Úkoly vyšší úrovně, které nejsou vytvořeny v kontextu jiného úkolu, se umístí do globální fronty stejně jako jakákoli jiná pracovní položka. Vnořené nebo podřízené úlohy, které jsou vytvořeny v kontextu jiné úlohy, se ale zpracovávají poměrně odlišně. Podřízená nebo vnořená úloha se umístí do místní fronty, která je specifická pro vlákno, na kterém je vykonávána nadřazená úloha. Nadřazený úkol může být úkol nejvyšší úrovně nebo také podřízeným úkolem jiného úkolu. Až bude vlákno připraveno na další práci, nejprve zkontroluje místní frontu. Pokud tam čekají pracovní položky, můžou se k nim dostat rychle. K místním frontám se přistupuje v pořadí poslední dovnitř, první ven (LIFO), aby se zachovala lokalita mezipaměti a snížily se konflikty. Další informace o podřízených úkolech a vnořených úkolech naleznete v tématu Připojené a odpojené podřízené úkoly.
Použití místních front nejen snižuje tlak na globální frontu, ale také využívá lokalitu dat. Pracovní položky v místní frontě často odkazují na datové struktury, které jsou fyzicky blízko sebe v paměti. V těchto případech jsou data již v mezipaměti po spuštění prvního úkolu a dají se k němu rychle získat přístup. Paralelní LINQ (PLINQ) i Parallel třída používají rozsáhle vnořené a podřízené úlohy a výrazně zrychlují díky využití místních pracovních front.
Krádež práce
Počínaje rozhraním .NET Framework 4 obsahuje fond vláken také algoritmus krádeže práce, který pomáhá zajistit, aby žádná vlákna neseděla nečinně, zatímco ostatní mají ještě práci ve svých frontách. Když je vlákno v poolu vláken připravené na další práci, nejprve prozkoumá začátek své místní fronty, poté globální frontu a nakonec místní fronty jiných vláken. Pokud najde pracovní položku v místní frontě jiného vlákna, nejprve použije heuristiky, aby se zajistilo, že může vykoná práci efektivně. Pokud ano, zruší frontu pracovní položky z chvostu (v pořadí FIFO). Tím se sníží kolize v každé místní frontě a zachová se umístění dat. Tato architektura pomáhá vyrovnávání zatížení fondu vláken efektivněji než předchozí verze.
Dlouhotrvající úlohy
Můžete chtít explicitně zabránit tomu, aby se úloha umístila do místní fronty. Například můžete vědět, že určitý pracovní úkol bude trvat poměrně dlouhou dobu a pravděpodobně zablokuje všechna ostatní práce v místní frontě. V tomto případě můžete zadat možnost System.Threading.Tasks.TaskCreationOptions, která plánovači poskytne nápovědu, že pro úlohu může být vyžadováno další vlákno, aby neblokovalo pokrok dalších vláken nebo pracovních položek v místní frontě. Využitím této možnosti se úplně vyhněte fondu vláken, včetně globálních a místních front.
Integrace úkolů
V některých případech, kdy se čeká na Task, může být spuštěn synchronně na vlákně, které provádí čekací operaci. Tím se zvýší výkon tím, že zabráníte nutnosti dalšího vlákna a místo toho použijete existující vlákno, které by jinak zablokovalo. Aby se zabránilo chybám způsobeným reentrantností, vložené úkoly nastanou pouze v případě, že se čekací cíl najde v lokální frontě příslušného vlákna.
Zadání kontextu synchronizace
Metodu TaskScheduler.FromCurrentSynchronizationContext můžete použít k určení, že má být úloha naplánována tak, aby běžela v určitém vlákně. To je užitečné v architekturách, jako jsou model Windows Forms a Windows Presentation Foundation, kde přístup k objektům uživatelského rozhraní je často omezen na kód spuštěný ve stejném vlákně, na kterém byl objekt uživatelského rozhraní vytvořen.
Následující příklad používá metodu TaskScheduler.FromCurrentSynchronizationContext v aplikaci WPF (Windows Presentation Foundation) (Windows Presentation Foundation) k naplánování úlohy ve stejném vlákně, ve které byl vytvořen ovládací prvek uživatelského rozhraní (UI). Příklad vytvoří mozaiku obrázků, které jsou náhodně vybrány ze zadaného adresáře. Objekty WPF (Windows Presentation Foundation) slouží k načtení a změně velikosti obrázků. Nezpracované pixely se pak předají úloze, která pomocí For smyčky zapisuje data pixelů do velkého pole s jedním bajtem. Nevyžaduje se žádná synchronizace, protože žádné dvě dlaždice nemají prvky stejného pole. Dlaždice lze také zapsat v libovolném pořadí, protože jejich pozice se počítá nezávisle na jakékoli jiné dlaždici. Velké pole se pak předá úloze, která běží ve vlákně uživatelského rozhraní, kde se data pixelů načtou do ovládacího prvku Image.
Příklad přesune data z vlákna uživatelského rozhraní, upraví je pomocí paralelních smyček a Task objektů a pak je předá zpět úloze, která běží ve vlákně uživatelského rozhraní. Tento přístup je užitečný v případě, že k provádění operací, které rozhraní WPF (Windows Presentation Foundation) API nepodporuje, musíte použít paralelní knihovnu úloh nebo nejsou dostatečně rychlé. Dalším způsobem, jak vytvořit obrázkovou mozaiku ve WPF (Windows Presentation Foundation), je použít System.Windows.Controls.WrapPanel ovládací prvek a přidat do něj obrázky. WrapPanel se stará o umístění dlaždic. Tuto práci však lze provést pouze ve vlákně uživatelského rozhraní.
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;
}
}
}
Pokud chcete vytvořit příklad, vytvořte projekt aplikace WPF (Windows Presentation Foundation) v sadě Visual Studio a pojmenujte ho WPF (Windows Presentation Foundation)_CS1 (pro projekt WPF (Windows Presentation Foundation) jazyka C#) nebo WPF (Windows Presentation Foundation)_VB1 (pro projekt WPF (Windows Presentation Foundation) jazyka Visual Basic). Potom udělejte následující:
V návrhovém zobrazení přetáhněte Image ovládací prvek ze sady nástrojů do levého horního rohu návrhové plochy. V textovém poli Název okna Vlastnosti pojmenujte ovládací prvek "image".
Button Přetáhněte ovládací prvek ze sady nástrojů do levé dolní části okna aplikace. V zobrazení XAML zadejte Content vlastnost tlačítka jako "Vytvořit mozaiku" a zadejte její Width vlastnost jako "100". Připojte událost Click k obslužné rutině události
button_Clickdefinované v kódu příkladu přidánímClick="button_Click"do elementu<Button>. V textovém poli Název okna Vlastnosti pojmenujte ovládací prvek "button".Celý obsah souboru MainWindow.xaml.cs nebo MainWindow.xaml.vb nahraďte kódem z tohoto příkladu. V případě projektu WPF (Windows Presentation Foundation) jazyka C# se ujistěte, že název pracovního prostoru odpovídá názvu projektu.
Příklad načte obrázky JPEG z adresáře S názvem C:\Users\Public\Pictures\Sample Pictures. Buď vytvořte adresář a umístěte do něj nějaké obrázky, nebo změňte cestu tak, aby odkazovat na jiný adresář, který obsahuje obrázky.
Tento příklad má určitá omezení. Podporují se například pouze 32bitové obrázky na pixel; obrázky v jiných formátech jsou objektem BitmapImage poškozeny během operace změny velikosti. Také zdrojové obrázky musí být větší než velikost dlaždice. Jako další cvičení můžete přidat funkce pro zpracování více formátů pixelů a velikostí souborů.
Konstruktory
| Name | Description |
|---|---|
| TaskScheduler() |
Inicializuje TaskScheduler. |
Vlastnosti
| Name | Description |
|---|---|
| Current |
TaskScheduler Získá přidruženou k aktuálně spuštěné úloze. |
| Default |
Získá výchozí instanci TaskScheduler, kterou poskytuje .NET. |
| Id |
Získá jedinečné ID pro toto TaskScheduler. |
| MaximumConcurrencyLevel |
Označuje maximální úroveň souběžnosti, která TaskScheduler je schopna podporovat. |
Metody
| Name | Description |
|---|---|
| Equals(Object) |
Určuje, zda je zadaný objekt roven aktuálnímu objektu. (Zděděno od Object) |
| Finalize() |
Uvolní všechny prostředky přidružené k tomuto plánovači. |
| FromCurrentSynchronizationContext() |
Vytvoří přidruženou TaskScheduler k aktuálnímu SynchronizationContext. |
| GetHashCode() |
Slouží jako výchozí funkce hash. (Zděděno od Object) |
| GetScheduledTasks() |
Pouze pro podporu ladicího programu vygeneruje výčet Task instancí aktuálně zařazených do fronty plánovače, který čeká na spuštění. |
| GetType() |
Získá Type aktuální instance. (Zděděno od Object) |
| MemberwiseClone() |
Vytvoří mělkou kopii aktuálního Object. (Zděděno od Object) |
| QueueTask(Task) |
Zařadí Task do fronty plánovače. |
| ToString() |
Vrátí řetězec, který představuje aktuální objekt. (Zděděno od Object) |
| TryDequeue(Task) |
Pokusí se odložit frontu dříve zařazeného Task do fronty tohoto plánovače. |
| TryExecuteTask(Task) |
Pokusí se provést poskytnuté Task v tomto plánovači. |
| TryExecuteTaskInline(Task, Boolean) |
Určuje, zda je možné zadané spuštění Task synchronně v tomto volání, a pokud ano, provede ho. |
Událost
| Name | Description |
|---|---|
| UnobservedTaskException |
Nastane v případě, že chybná výjimka úlohy, která není vyhrazena, se chystá aktivovat zásady eskalace výjimek, které by ve výchozím nastavení proces ukončily. |
Platí pro
Bezpečný přístup z více vláken
Všichni členové abstraktního TaskScheduler typu jsou bezpečné pro přístup z více vláken a mohou být použity současně z více vláken.