Compartir a través de


Envía un elemento de trabajo al grupo de hilos

[ Actualizado para aplicaciones para UWP en Windows 10. Para los artículos de Windows 8.x, consulta el archivo ]

Las APIs importantes

Aprenda a trabajar en un subproceso independiente mediante el envío de un elemento de trabajo al grupo de subprocesos. Úselo para mantener una interfaz de usuario con capacidad de respuesta mientras sigue completando el trabajo que tarda un período de tiempo notable y úselo para completar varias tareas en paralelo.

Creación y envío del elemento de trabajo

Cree un elemento de trabajo llamando a RunAsync. Proporcione un delegado para realizar el trabajo (puede usar una función lambda o una función de delegado). Tenga en cuenta que RunAsync devuelve un objeto IAsyncAction; almacene este objeto para usarlo en el paso siguiente.

Hay tres versiones de RunAsync disponibles para que pueda especificar opcionalmente la prioridad del elemento de trabajo y controlar si se ejecuta simultáneamente con otros elementos de trabajo.

Nota:

Utilice el método CoreDispatcher.RunAsync para acceder al subproceso de la interfaz de usuario y mostrar el progreso del elemento de trabajo.

En el ejemplo siguiente se crea un elemento de trabajo y se proporciona una expresión lambda para realizar el trabajo:

// 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;

Después de la llamada a RunAsync, el grupo de subprocesos pone en cola el elemento de trabajo, que se ejecuta cuando hay un subproceso disponible. Los elementos de trabajo del grupo de subprocesos se ejecutan de forma asincrónica y se pueden ejecutar en cualquier orden, por lo que asegúrese de que cada tarea funcione de manera independiente.

Tenga en cuenta que el elemento de trabajo comprueba la propiedad IAsyncInfo.Status y sale si se cancela el elemento de trabajo.

Gestionar la finalización de elementos de trabajo

Proporcione un controlador de finalización estableciendo la propiedad IAsyncAction.Completed del elemento de trabajo. Proporcione un delegado (puede usar una lambda o una función delegada) para gestionar la finalización de los elementos de trabajo. Por ejemplo, use CoreDispatcher.RunAsync para acceder al subproceso de interfaz de usuario y mostrar el resultado.

En el ejemplo siguiente se actualiza la interfaz de usuario con el resultado del elemento de trabajo enviado en el paso 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);
    }));
});

Tenga en cuenta que el controlador de finalización comprueba si el elemento de trabajo se canceló antes de enviar una actualización de la interfaz de usuario.

Resumen y pasos siguientes

Para obtener más información, descargue el código de esta guía de inicio rápido en el ejemplo "Creating a ThreadPool work item" escrito para Windows 8.1 y reutilice el código fuente en una aplicación Windows 10 win_unap.