Mengirimkan item kerja ke kumpulan utas

[ Diperbarui untuk aplikasi UWP di Windows 10. Untuk artikel Windows 8.x, lihat arsip ]

API penting

Pelajari cara melakukan pekerjaan di utas terpisah dengan mengirimkan item kerja ke kumpulan utas. Gunakan ini untuk mempertahankan UI responsif sambil tetap menyelesaikan pekerjaan yang membutuhkan waktu yang nyata, dan gunakan untuk menyelesaikan beberapa tugas secara paralel.

Membuat dan mengirimkan item kerja

Buat item kerja dengan memanggil RunAsync. Berikan delegasi untuk melakukan pekerjaan (Anda dapat menggunakan lambda, atau fungsi delegasi). Perhatikan bahwa RunAsync mengembalikan objek IAsyncAction ; simpan objek ini untuk digunakan di langkah berikutnya.

Tiga versi RunAsync tersedia sehingga Anda dapat secara opsional menentukan prioritas item kerja, dan mengontrol apakah item tersebut berjalan bersamaan dengan item kerja lainnya.

Catatan

Gunakan CoreDispatcher.RunAsync untuk mengakses utas UI dan memperlihatkan kemajuan dari item kerja.

Contoh berikut membuat item kerja dan memasok lambda untuk melakukan pekerjaan:

// The nth prime number to find.
const uint n = 9999;

// Receives the result.
ulong nthPrime = 0;

// Simulates work by searching for the nth prime number. Uses a
// naive algorithm and counts 2 as the first prime number.
IAsyncAction asyncAction = Windows.System.Threading.ThreadPool.RunAsync(
    (workItem) =>
{
    uint  progress = 0; // For progress reporting.
    uint  primes = 0;   // Number of primes found so far.
    ulong i = 2;        // Number iterator.

    if ((n >= 0) && (n <= 2))
    {
        nthPrime = n;
        return;
    }

    while (primes < (n - 1))
    {
        if (workItem.Status == AsyncStatus.Canceled)
        {
            break;
        }

        // Go to the next number.
        i++;

        // Check for prime.
        bool prime = true;
        for (uint j = 2; j < i; ++j)
        {
            if ((i % j) == 0)
            {
                prime = false;
                break;
            }
        };

        if (prime)
        {
            // Found another prime number.
            primes++;

            // Report progress at every 10 percent.
            uint temp = progress;
            progress = (uint)(10.0*primes/n);

            if (progress != temp)
            {
                String updateString;
                updateString = "Progress to " + n + "th prime: "
                    + (10 * progress) + "%\n";

                // Update the UI thread with the CoreDispatcher.
                CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
                    CoreDispatcherPriority.High,
                    new DispatchedHandler(() =>
                {
                    UpdateUI(updateString);
                }));
            }
        }
    }

    // Return the nth prime number.
    nthPrime = i;
});

// A reference to the work item is cached so that we can trigger a
// cancellation when the user presses the Cancel button.
m_workItem = asyncAction;
// The nth prime number to find.
const unsigned int n{ 9999 };

// A shared pointer to the result.
// We use a shared pointer to keep the result alive until the
// work is done.
std::shared_ptr<unsigned long> nthPrime = std::make_shared<unsigned long>(0);

// Simulates work by searching for the nth prime number. Uses a
// naive algorithm and counts 2 as the first prime number.

// A reference to the work item is cached so that we can trigger a
// cancellation when the user presses the Cancel button.
m_workItem = Windows::System::Threading::ThreadPool::RunAsync(
    [=, strongThis = get_strong()](Windows::Foundation::IAsyncAction const& workItem)
{
    unsigned int progress = 0; // For progress reporting.
    unsigned int primes = 0;   // Number of primes found so far.
    unsigned long int i = 2;   // Number iterator.

    if ((n >= 0) && (n <= 2))
    {
        *nthPrime = n;
        return;
    }

    while (primes < (n - 1))
    {
        if (workItem.Status() == Windows::Foundation::AsyncStatus::Canceled)
        {
            break;
        }

        // Go to the next number.
        i++;

        // Check for prime.
        bool prime = true;
        for (unsigned int j = 2; j < i; ++j)
        {
            if ((i % j) == 0)
            {
                prime = false;
                break;
            }
        };

        if (prime)
        {
            // Found another prime number.
            primes++;

            // Report progress at every 10 percent.
            unsigned int temp = progress;
            progress = static_cast<unsigned int>(10.f*primes / n);

            if (progress != temp)
            {
                std::wstringstream updateStream;
                updateStream << L"Progress to " << n << L"th prime: " << (10 * progress) << std::endl;
                std::wstring updateString = updateStream.str();

                // Update the UI thread with the CoreDispatcher.
                Windows::ApplicationModel::Core::CoreApplication::MainView().CoreWindow().Dispatcher().RunAsync(
                    Windows::UI::Core::CoreDispatcherPriority::High,
                    Windows::UI::Core::DispatchedHandler([=]()
                {
                    strongThis->UpdateUI(updateString);
                }));
            }
        }
    }
    // Return the nth prime number.
    *nthPrime = i;
});
// The nth prime number to find.
const unsigned int n = 9999;

// A shared pointer to the result.
// We use a shared pointer to keep the result alive until the
// work is done.
std::shared_ptr<unsigned long> nthPrime = std::make_shared<unsigned long>(0);

// Simulates work by searching for the nth prime number. Uses a
// naive algorithm and counts 2 as the first prime number.
auto workItem = ref new Windows::System::Threading::WorkItemHandler(
    [this, n, nthPrime](IAsyncAction^ workItem)
{
    unsigned int progress = 0; // For progress reporting.
    unsigned int primes = 0;   // Number of primes found so far.
    unsigned long int i = 2;   // Number iterator.

    if ((n >= 0) && (n <= 2))
    {
        *nthPrime = n;
        return;
    }

    while (primes < (n - 1))
    {
        if (workItem->Status == AsyncStatus::Canceled)
       {
           break;
       }

       // Go to the next number.
       i++;

       // Check for prime.
       bool prime = true;
       for (unsigned int j = 2; j < i; ++j)
       {
           if ((i % j) == 0)
           {
               prime = false;
               break;
           }
       };

       if (prime)
       {
           // Found another prime number.
           primes++;

           // Report progress at every 10 percent.
           unsigned int temp = progress;
           progress = static_cast<unsigned int>(10.f*primes / n);

           if (progress != temp)
           {
               String^ updateString;
               updateString = "Progress to " + n + "th prime: "
                   + (10 * progress).ToString() + "%\n";

               // Update the UI thread with the CoreDispatcher.
               CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
                   CoreDispatcherPriority::High,
                   ref new DispatchedHandler([this, updateString]()
               {
                   UpdateUI(updateString);
               }));
           }
       }
   }
   // Return the nth prime number.
   *nthPrime = i;
});

auto asyncAction = ThreadPool::RunAsync(workItem);

// A reference to the work item is cached so that we can trigger a
// cancellation when the user presses the Cancel button.
m_workItem = asyncAction;

Setelah panggilan ke RunAsync, item kerja diantrekan oleh kumpulan utas dan berjalan saat utas tersedia. Item kerja kumpulan utas berjalan secara asinkron dan dapat berjalan dalam urutan apa pun, jadi pastikan item kerja Anda berfungsi secara independen.

Perhatikan bahwa item kerja memeriksa properti IAsyncInfo.Status , dan keluar jika item kerja dibatalkan.

Menangani penyelesaian item kerja

Berikan handler penyelesaian dengan mengatur properti IAsyncAction.Completed dari item kerja. Berikan delegasi (Anda dapat menggunakan fungsi lambda atau delegasi) untuk menangani penyelesaian item kerja. Misalnya, gunakan CoreDispatcher.RunAsync untuk mengakses utas UI dan menampilkan hasilnya.

Contoh berikut memperbarui UI dengan hasil item kerja yang dikirimkan di langkah 1:

asyncAction->Completed = ref new AsyncActionCompletedHandler(
    [this, n, nthPrime](IAsyncAction^ asyncInfo, AsyncStatus asyncStatus)
{
    if (asyncStatus == AsyncStatus::Canceled)
    {
        return;
    }

    String^ updateString;
    updateString = "\n" + "The " + n + "th prime number is "
        + (*nthPrime).ToString() + ".\n";

    // Update the UI thread with the CoreDispatcher.
    CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
        CoreDispatcherPriority::High,
        ref new DispatchedHandler([this, updateString]()
    {
        UpdateUI(updateString);
    }));
});
m_workItem.Completed(
    [=, strongThis = get_strong()](Windows::Foundation::IAsyncAction const& asyncInfo, Windows::Foundation::AsyncStatus const& asyncStatus)
{
    if (asyncStatus == Windows::Foundation::AsyncStatus::Canceled)
    {
        return;
    }

    std::wstringstream updateStream;
    updateStream << std::endl << L"The " << n << L"th prime number is " << *nthPrime << std::endl;
    std::wstring updateString = updateStream.str();

    // Update the UI thread with the CoreDispatcher.
    Windows::ApplicationModel::Core::CoreApplication::MainView().CoreWindow().Dispatcher().RunAsync(
        Windows::UI::Core::CoreDispatcherPriority::High,
        Windows::UI::Core::DispatchedHandler([=]()
    {
        strongThis->UpdateUI(updateString);
    }));
});
asyncAction.Completed = new AsyncActionCompletedHandler(
    (IAsyncAction asyncInfo, AsyncStatus asyncStatus) =>
{
    if (asyncStatus == AsyncStatus.Canceled)
    {
        return;
    }

    String updateString;
    updateString = "\n" + "The " + n + "th prime number is "
        + nthPrime + ".\n";

    // Update the UI thread with the CoreDispatcher.
    CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
        CoreDispatcherPriority.High,
        new DispatchedHandler(()=>
    {
        UpdateUI(updateString);
    }));
});

Perhatikan bahwa handler penyelesaian memeriksa apakah item kerja dibatalkan sebelum mengirimkan pembaruan UI.

Ringkasan dan langkah berikutnya

Anda dapat mempelajari lebih lanjut dengan mengunduh kode dari mulai cepat ini di sampel Membuat item kerja ThreadPool yang ditulis untuk Windows 8.1, dan menggunakan kembali kode sumber di aplikasi win_unap Windows 10.