TaskScheduler Kelas
Definisi
Penting
Beberapa informasi terkait produk prarilis yang dapat diubah secara signifikan sebelum dirilis. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.
Mewakili objek yang menangani pekerjaan tingkat rendah tugas antrean ke utas.
public ref class TaskScheduler abstract
public abstract class TaskScheduler
type TaskScheduler = class
Public MustInherit Class TaskScheduler
- Warisan
-
TaskScheduler
Contoh
Contoh berikut membuat penjadwal tugas kustom yang membatasi jumlah utas yang digunakan oleh aplikasi. Kemudian meluncurkan dua set tugas dan menampilkan informasi tentang tugas dan utas tempat tugas dijalankan.
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
Keterangan
Kelas TaskScheduler mewakili penjadwal tugas. Penjadwal tugas memastikan bahwa pekerjaan tugas akhirnya dijalankan.
Penjadwal tugas default menyediakan pencurian kerja untuk penyeimbangan beban, injeksi/penghentian utas untuk throughput maksimum, dan performa yang baik secara keseluruhan. Ini harus cukup untuk sebagian besar skenario.
Kelas ini TaskScheduler juga berfungsi sebagai titik ekstensi untuk semua logika penjadwalan yang dapat disesuaikan. Ini termasuk mekanisme seperti cara menjadwalkan tugas untuk eksekusi, dan bagaimana tugas terjadwal harus diekspos ke debugger. Jika Anda memerlukan fungsionalitas khusus, Anda dapat membuat penjadwal kustom dan mengaktifkannya untuk tugas atau kueri tertentu.
Penjadwal tugas bawaan dan kumpulan thread
Penjadwal default untuk Pustaka Paralel Tugas dan PLINQ menggunakan kumpulan utas .NET, yang diwakili oleh kelas ThreadPool, untuk menjadwalkan dan menjalankan pekerjaan. Grup koneksi utas menggunakan informasi yang disediakan oleh tipe Task untuk secara efisien mendukung paralelisme butir halus (unit kerja berumur pendek) yang secara umum dihasilkan oleh tugas dan kueri paralel.
Antrean global vs. antrean lokal
Kumpulan utas mempertahankan antrean kerja FIFO global (first-in, first-out) untuk utas di setiap domain aplikasi. Setiap kali program memanggil metode ThreadPool.QueueUserWorkItem (atau ThreadPool.UnsafeQueueUserWorkItem), pekerjaan diletakkan pada antrean bersama ini dan akhirnya dipindahkan dari antrean ke utas yang tersedia berikutnya. Dimulai dengan .NET Framework 4, antrean ini menggunakan algoritma bebas kunci yang menyerupai kelas ConcurrentQueue<T>. Dengan menggunakan implementasi bebas kunci ini, kumpulan utas menghabiskan lebih sedikit waktu saat mengantre dan membatalkan antrean item kerja. Manfaat performa ini tersedia untuk semua program yang menggunakan thread pool.
Tugas tingkat atas, yang merupakan tugas yang tidak dibuat dalam konteks tugas lain, diletakkan pada antrean global seperti item kerja lainnya. Namun, tugas bertingkat atau subtugas, yang dibuat dalam konteks tugas lain, ditangani dengan cara yang berbeda. Tugas anak atau tugas bersarang ditempatkan pada antrean lokal yang khusus untuk utas di mana tugas induk dijalankan. Tugas induk mungkin merupakan tugas tingkat tinggi atau mungkin juga bagian dari tugas lain. Ketika utas ini siap untuk lebih banyak pekerjaan, pertama-tama terlihat dalam antrean lokal. Jika item kerja menunggu di sana, item dapat diakses dengan cepat. Antrean lokal diakses dalam urutan terakhir masuk, pertama keluar (LIFO) untuk mempertahankan lokalitas cache dan mengurangi persaingan. Untuk informasi selengkapnya tentang tugas anak dan tugas berlapis, lihat Tugas Anak Terlampir dan Terlepas.
Penggunaan antrean lokal tidak hanya mengurangi tekanan pada antrean global, tetapi juga memanfaatkan lokalitas data. Item kerja dalam antrean lokal sering merujuk struktur data yang secara fisik berdekatan dalam memori. Dalam kasus ini, data sudah ada di cache setelah tugas pertama berjalan dan dapat diakses dengan cepat. Baik Parallel LINQ (PLINQ) maupun kelas Parallel menggunakan tugas berlapis dan tugas anak secara ekstensif, dan pencapaian peningkatan kecepatan yang signifikan dengan menggunakan antrean pekerjaan lokal.
Mencuri pekerjaan
Dimulai dengan .NET Framework 4, thread pool juga memiliki algoritma pencurian kerja untuk membantu memastikan bahwa tidak ada utas yang menganggur sementara utas lain masih memiliki pekerjaan dalam antrean. Ketika utas dari kumpulan utas siap untuk menangani lebih banyak pekerjaan, pertama-tama melihat bagian depan antrean lokalnya, kemudian dalam antrean global, dan kemudian dalam antrean lokal utas lain. Jika menemukan item kerja dalam antrean lokal utas lain, pertama-tama ia menerapkan heuristik untuk memastikan bahwa item kerja tersebut dapat dijalankan secara efisien. Jika bisa, item kerja dibatalkan antreannya dari ekor (dalam urutan FIFO). Ini mengurangi perebutan pada setiap antrean lokal dan mempertahankan lokalitas data. Arsitektur ini membantu pool utas menyeimbangkan beban kerja secara lebih efisien dibandingkan dengan versi sebelumnya.
Tugas jangka panjang
Anda mungkin ingin secara eksplisit mencegah tugas dimasukkan ke antrean lokal. Misalnya, Anda mungkin tahu bahwa item kerja tertentu akan berjalan untuk waktu yang relatif lama dan kemungkinan akan menghalangi semua item kerja lainnya di antrean lokal. Dalam hal ini, Anda dapat menentukan System.Threading.Tasks.TaskCreationOptions sebagai opsi, yang memberikan petunjuk kepada penjadwal bahwa kemungkinan diperlukan utas tambahan untuk tugas agar tidak memblokir kemajuan dari utas lain atau item kerja pada antrian lokal. Dengan memilih opsi ini, Anda menghindari kumpulan utas sepenuhnya, termasuk antrean global dan lokal.
Penyisipan tugas
Dalam beberapa kasus, ketika Task sedang ditunggu, komponen itu dapat dijalankan secara sinkron pada utas yang terkait dengan operasi tunggu tersebut. Ini meningkatkan performa dengan mencegah penggunaan utas tambahan dan alih-alih menggunakan utas yang ada, yang sebaliknya akan diblokir. Untuk mencegah kesalahan karena reentri, penyisipan tugas hanya terjadi ketika target tunggu ditemukan di antrean lokal dari utas yang bersangkutan.
Tentukan konteks sinkronisasi
Anda dapat menggunakan metode TaskScheduler.FromCurrentSynchronizationContext untuk menentukan bahwa tugas harus dijadwalkan untuk dijalankan pada utas tertentu. Ini berguna dalam kerangka kerja seperti Formulir Windows dan Windows Presentation Foundation di mana akses ke objek antarmuka pengguna sering dibatasi untuk kode yang berjalan pada utas yang sama tempat objek UI dibuat.
Contoh berikut menggunakan metode dalam aplikasi Windows Presentation Foundation (WPF) untuk menjadwalkan tugas pada utas TaskScheduler.FromCurrentSynchronizationContext yang sama dengan tempat kontrol antarmuka pengguna (UI) dibuat. Contoh membuat mosaik gambar yang dipilih secara acak dari direktori tertentu. Objek WPF digunakan untuk memuat dan mengubah ukuran gambar. Piksel mentah kemudian diteruskan ke tugas yang menggunakan perulangan For untuk menulis data piksel ke dalam array byte tunggal besar. Tidak diperlukan sinkronisasi karena tidak ada dua petak peta yang menempati elemen array yang sama. Petak peta juga dapat ditulis dalam urutan apa pun karena posisinya dihitung secara independen dari petak peta lainnya. Array besar kemudian diteruskan ke tugas yang berjalan pada utas UI, di mana data piksel dimuat ke dalam pengendali Gambar.
Contoh memindahkan data dari utas UI, memodifikasinya dengan menggunakan perulangan dan Task objek paralel, lalu meneruskannya kembali ke tugas yang berjalan pada utas UI. Pendekatan ini berguna ketika Anda harus menggunakan Pustaka Paralel Tugas untuk melakukan operasi yang tidak didukung oleh API WPF, atau yang kinerjanya tidak cukup cepat. Cara lain untuk membuat mosaik gambar di WPF adalah dengan menggunakan System.Windows.Controls.WrapPanel kontrol dan menambahkan gambar ke dalamnya. WrapPanel menangani pekerjaan penempatan petak. Namun, pekerjaan ini hanya bisa dilakukan pada utas antarmuka pengguna.
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;
}
}
}
Untuk membuat contoh, buat proyek aplikasi WPF di Visual Studio dan beri nama WPF_CS1 (untuk proyek C# WPF) atau WPF_VB1 (untuk proyek Visual Basic WPF). Lalu, lakukan hal berikut:
Dalam tampilan desain, seret Image kontrol dari Kotak Alat ke sudut kiri atas permukaan desain. Di kotak teks Nama jendela Properti , beri nama kontrol "gambar".
Button Seret kontrol dari Kotak Alat ke bagian kiri bawah jendela aplikasi. Dalam tampilan XAML, tentukan Content properti tombol sebagai "Buat mosaik", dan tentukan propertinya Width sebagai "100". Sambungkan Click peristiwa dengan penangan peristiwa yang
button_Clickditentukan dalam kode contoh dengan menambahkanClick="button_Click"ke elemen<Button>. Di kotak teks Nama jendela Properti , beri nama tombol kontrol "".Ganti seluruh konten file MainWindow.xaml.cs atau MainWindow.xaml.vb dengan kode dari contoh ini. Untuk proyek C# WPF, pastikan bahwa nama ruang kerja cocok dengan nama proyek.
Contoh membaca gambar JPEG dari direktori bernama C:\Users\Public\Pictures\Sample Pictures. Buat direktori dan tempatkan beberapa gambar di dalamnya, atau ubah jalur untuk merujuk ke beberapa direktori lain yang berisi gambar.
Contoh ini memiliki beberapa batasan. Misalnya, hanya gambar 32-bit per piksel yang didukung; gambar dalam format lain rusak oleh BitmapImage objek selama operasi mengubah ukuran. Selain itu, semua gambar sumber harus lebih besar dari ukuran petak peta. Sebagai latihan lebih lanjut, Anda dapat menambahkan fungsionalitas untuk menangani beberapa format piksel dan ukuran file.
Konstruktor
| Nama | Deskripsi |
|---|---|
| TaskScheduler() |
Menginisialisasi TaskScheduler. |
Properti
| Nama | Deskripsi |
|---|---|
| Current |
Mendapatkan yang TaskScheduler terkait dengan tugas yang sedang dijalankan. |
| Default |
Mendapatkan instans TaskScheduler default yang disediakan oleh .NET. |
| Id |
Mendapatkan ID unik untuk ini TaskScheduler. |
| MaximumConcurrencyLevel |
Menunjukkan tingkat konkurensi maksimum yang TaskScheduler dapat didukung. |
Metode
| Nama | Deskripsi |
|---|---|
| Equals(Object) |
Menentukan apakah objek yang ditentukan sama dengan objek saat ini. (Diperoleh dari Object) |
| Finalize() |
Membebaskan semua sumber daya yang terkait dengan penjadwal ini. |
| FromCurrentSynchronizationContext() |
Membuat yang TaskScheduler terkait dengan saat ini SynchronizationContext. |
| GetHashCode() |
Berfungsi sebagai fungsi hash default. (Diperoleh dari Object) |
| GetScheduledTasks() |
Hanya untuk dukungan debugger, menghasilkan enumerable Task instans yang saat ini diantrekan ke penjadwal yang menunggu untuk dijalankan. |
| GetType() |
Mendapatkan Type instans saat ini. (Diperoleh dari Object) |
| MemberwiseClone() |
Membuat salinan dangkal dari Objectsaat ini. (Diperoleh dari Object) |
| QueueTask(Task) |
Mengantre ke Task penjadwal. |
| ToString() |
Mengembalikan string yang mewakili objek saat ini. (Diperoleh dari Object) |
| TryDequeue(Task) |
Mencoba untuk menghapus antrean Task yang sebelumnya diantrekan ke penjadwal ini. |
| TryExecuteTask(Task) |
Mencoba menjalankan yang disediakan Task pada penjadwal ini. |
| TryExecuteTaskInline(Task, Boolean) |
Menentukan apakah yang disediakan Task dapat dijalankan secara sinkron dalam panggilan ini, dan jika bisa, menjalankannya. |
Acara
| Nama | Deskripsi |
|---|---|
| UnobservedTaskException |
Terjadi ketika pengecualian tugas yang tidak ditangguhkan yang rusak akan memicu kebijakan eskalasi pengecualian, yang, secara default, akan mengakhiri proses. |
Berlaku untuk
Keamanan Thread
Semua anggota jenis abstrak TaskScheduler aman utas dan dapat digunakan dari beberapa utas secara bersamaan.