Aracılığıyla paylaş


Görev paralellik (eşzamanlılık çalışma zamanı)

Bu belgeyi görevler ve Görev grupları eşzamanlılık çalışma zamanında görevini açıklar. A görev belirli bir işin gerçekleştirdiği iş birimidir. Genellikle bir görev diğer görevler ile paralel çalışır ve ek, daha iyi ayarlanmış görevler decomposed. A görev grubu görevleri topluluğu düzenler.

Görevleri zaman uyumsuz kod yazmak ve zaman uyumsuz işlem tamamlandıktan sonra gerçekleşmesi için bazı işlemi istediğinizde kullanın. Örneğin, bir görev dosyasındaki ve kullanılabilir olduktan sonra verileri işlemek için bu belgede daha sonra açıklandığı bir devamı görev zaman uyumsuz olarak okumak için kullanabilir. Tersine, daha küçük parçalara paralel iş decompose için görev gruplarını kullanın. Örneğin, kalan çalışmanın iki bölüme ayıran bir özyinelemeli algoritması olduğunu varsayalım. Bu bölümler aynı anda çalıştırmak ve bölünmüş çalışmayı tamamlamak beklemek için görev gruplarını kullanabilirsiniz.

İpucu

Her öğe koleksiyonu paralel, aynı yordamı uygulamak istediğinizde, bir paralel algoritması gibi kullanın concurrency::parallel_for, görev veya görev grubu yerine.Paralel algoritmalar hakkında daha fazla bilgi için bkz: Paralel algoritmalar.

Önemli noktalar

  • Lambda ifade başvuruya göre değişken geçirdiğinizde görev bitene kadar o değişkenin yaşam kalır etmeleri gerekir.

  • Kullanım görevleri ( concurrency::task class) yazmak ne zaman zaman uyumsuz kod.

  • Görev gruplarını kullanın (gibi concurrency::task_group class ya da concurrency::parallel_invoke algoritması) gerektiğinde daha küçük parçalara paralel iş decompose ve bu küçük parça tamamlamak bekleyin.

  • Use concurrency::task::then continuations oluşturma yöntemi. A devamı başka bir görev tamamlandıktan sonra zaman uyumsuz olarak çalışır bir görevdir. Zaman uyumsuz iş zinciri oluşturmak için continuations herhangi bir sayıda bağlanabilirsiniz.

  • Öncül görevin sona erdiğinde, hatta ne zaman öncül görev iptal edilir veya bir istisna atar görev tabanlı devamı her zaman çalıştırılmak üzere planlanmıştır.

  • Use concurrency::when_all her üye bir dizi görevi tamamlandıktan sonra tamamlar bir görev oluşturmak için. Use concurrency::when_any bir üye bir dizi görevi tamamlandıktan sonra tamamlar bir görev oluşturmak için.

  • ppl iptali mekanizması, görevleri ve Görev grupları katılabilir. Daha fazla bilgi için bkz. ppl iptali.

  • Görevler ve Görev grupları tarafından atılan istisnalar çalışma zamanı nasıl işlediğini öğrenmek için bkz: Özel durum işleme eşzamanlılık çalışma zamanında.

Bu belgede yer alan

  • Lambda ifadeleri kullanma

  • Görev sınıfı

  • Devamı görevleri

  • Değere göre görev tabanlı Continuations karşı

  • Görevler oluşturma

    • When_all işlevi

    • When_any işlevi

  • Geciken görev yürütme

  • Görev Grupları

  • Structured_task_group task_group karşılaştırması

  • Örnek

  • Güçlü programlama

Lambda ifadeleri kullanma

Lambda ifadeleri Sözün kendi sözdizimi görevleri ve Görev grupları tarafından gerçekleştirilen çalışma tanımlamak için yaygın bir yoldur. Bunları kullanma hakkında bazı ipuçları verilmiştir:

  • Görevler genellikle arka plan iş parçacığı üzerinde çalıştığından, değişkenleri lambda ifadelerde yakalama ne zaman nesnenin ömrü unutmayın. Bir değişkenin değerine göre yakaladığınızda bu değişkenin bir kopyası lambda gövdeye yapılır. Başvuruya göre yakaladığınızda, bir kopyası bırakılmaz. Bu nedenle, herhangi bir değişkenin başvurusu tarafından yakalama yaşam kullandığı görev outlives emin olun.

  • Genel olarak, yakalama olmayan değişkenler tarafından yığında tahsis. Bu da, yýðýndaki ayrýlan nesnelerinin üyesi değişkenleri yakalamak gerekir anlamına gelir.

  • Ne, değer olarak başvuruya göre yakalama tanımlamanıza yardımcı olması için lambda ifadelerde yakalama değişkenler hakkında açık olması. Bu nedenle verme öneririz, kullandığınız [=] veya [&] lambda ifadeleri seçenekleri.

Ortak bir desen, bir göreve devamı zincirindeki bir değişkene atar ve bu değişkeni başka bir göreve okur gerçekleşir. Çünkü her devamı görev bu değişkeni farklı bir kopyasını tutan değerine göre yakalayamazsınız. Yığın ayrılan değişkenleri, değişken artık geçerli olmayabilir çünkü başvuruya göre de yakalayamazsınız.

Bu sorunu çözmek için bir akıllı işaretçi gibi kullanmak std::shared_ptr, değişken sarma ve değerine göre Akıllı işaretçi geçirmek için. Bunu yaparak, alttaki nesne atanabilir ve okuma ve onu kullanan görevleri outlive. Değişken bir işaretçi veya başvuru sayılan tanıtıcı olsa bile bu tekniği kullanın (^) Windows çalışma zamanı nesnesi. Temel bir örneği aşağıdadır:

// lambda-task-lifetime.cpp
// compile with: /EHsc
#include <ppltasks.h>
#include <iostream>
#include <string>

using namespace concurrency;
using namespace std;

task<wstring> write_to_string()
{
    // Create a shared pointer to a string that is 
    // assigned to and read by multiple tasks.
    // By using a shared pointer, the string outlives
    // the tasks, which can run in the background after
    // this function exits.
    auto s = make_shared<wstring>(L"Value 1");

    return create_task([s] 
    {
        // Print the current value.
        wcout << L"Current value: " << *s << endl;
        // Assign to a new value.
        *s = L"Value 2";

    }).then([s] 
    {
        // Print the current value.
        wcout << L"Current value: " << *s << endl;
        // Assign to a new value and return the string.
        *s = L"Value 3";
        return *s;
    });
}

int wmain()
{
    // Create a chain of tasks that work with a string.
    auto t = write_to_string();

    // Wait for the tasks to finish and print the result.
    wcout << L"Final value: " << t.get() << endl;
}

/* Output:
    Current value: Value 1
    Current value: Value 2
    Final value: Value 3
*/

Lambda ifadeleri hakkında daha fazla bilgi için bkz: Lambda ifadeleri C++.

Top

Görev sınıfı

Kullanabileceğiniz concurrency::task görevleri kümesi bağımlı işlemler oluşturmak için sınıf. Bu kompozisyon model kavramı tarafından desteklenen continuations. Ne zaman yürütülmeye devam etkinleştirir kod önceki, ya da antecedent, görevi tamamlar. Öncül görev sonucu bir veya daha fazla devamı görevler için giriş olarak geçirilir. Öncül görev tamamlandığında üzerinde bekleyen herhangi bir devamı görevler çalıştırılmak üzere zamanlanır. Her devamı görev sonucu öncül görevin bir kopyasını alır. Sırasıyla devamı görevlerle böylece görevlerin bir zincir oluşturmak, diğer continuations için öncül görevler de olabilir. Continuations rasgele uzunluklarda zincirleri aralarında belirli bağımlılıkları olan görevleri oluşturmanıza yardımcı olur. Buna ek olarak, çalışırken görev iptali ya da önce bir görev başlatılır veya işbirlikçi bir şekilde katılabilirler. Bu iptali modeli hakkında daha fazla bilgi için bkz: ppl iptali.

taskŞablon sınıfıdır. Type parametresi T görevi tarafından üretilen sonuç türüdür. Bu tür olabilir void , görev bir değer döndürmez. Tkullanamazsınız const değiştiricisi.

Bir görev oluşturduğunuzda sağladığınız bir iş işlevi , görev gövde gerçekleştirir. Bu iş işlevi lambda işlevi, işlev işaretçisi veya işlev nesne şeklinde gelir. Arama sonucu elde edilmeden bitirmek bir görev için beklemek için concurrency::task::wait yöntemi. task::wait Yöntemi döndürür bir concurrency::task_status görevin tamamlandığını veya iptal edildiğini tanımlayan değer. Görev sonucu elde etmek için arama concurrency::task::get yöntemi. Bu yöntem çağrıları task::wait görevin bitiş ve bu nedenle geçerli iş parçacığı yürütülmesini engeller sonucu kullanılabilir duruma gelene kadar beklemek.

Aşağıdaki örnek, bir görev oluşturmak için sonucu bekleyin ve değerini görüntülemek nasıl gösterir. Bu belgedeki örneklerde daha Sözün sözdizimi sağladıklarından lambda işlevlerini kullanın. Ancak, görevler kullandığınızda da işlev işaretçileri ve function nesnelerini kullanabilirsiniz.

// basic-task.cpp
// compile with: /EHsc
#include <ppltasks.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
    // Create a task.
    task<int> t([]()
    {
        return 42;
    });

    // In this example, you don't necessarily need to call wait() because
    // the call to get() also waits for the result.
    t.wait();

    // Print the result.
    wcout << t.get() << endl;
}

/* Output:
    42
*/

Concurrency::create_task işlevi kullanmanıza olanak sağlayan auto türü bildirmek yerine anahtar sözcüğü. Örneğin, aşağıdaki kod oluşturup matrisini yazdırır göz önünde bulundurun:

// create-task.cpp
// compile with: /EHsc
#include <ppltasks.h>
#include <string>
#include <iostream>
#include <array>

using namespace concurrency;
using namespace std;

int wmain()
{
    task<array<array<int, 10>, 10>> create_identity_matrix([]
    {
        array<array<int, 10>, 10> matrix;
        int row = 0;
        for_each(begin(matrix), end(matrix), [&row](array<int, 10>& matrixRow) 
        {
            fill(begin(matrixRow), end(matrixRow), 0);
            matrixRow[row] = 1;
            row++;
        });
        return matrix;
    });

    auto print_matrix = create_identity_matrix.then([](array<array<int, 10>, 10> matrix)
    {
        for_each(begin(matrix), end(matrix), [](array<int, 10>& matrixRow) 
        {
            wstring comma;
            for_each(begin(matrixRow), end(matrixRow), [&comma](int n) 
            {
                wcout << comma << n;
                comma = L", ";
            });
            wcout << endl;
        });
    });

    print_matrix.wait();
}
/* Output:
    1, 0, 0, 0, 0, 0, 0, 0, 0, 0
    0, 1, 0, 0, 0, 0, 0, 0, 0, 0
    0, 0, 1, 0, 0, 0, 0, 0, 0, 0
    0, 0, 0, 1, 0, 0, 0, 0, 0, 0
    0, 0, 0, 0, 1, 0, 0, 0, 0, 0
    0, 0, 0, 0, 0, 1, 0, 0, 0, 0
    0, 0, 0, 0, 0, 0, 1, 0, 0, 0
    0, 0, 0, 0, 0, 0, 0, 1, 0, 0
    0, 0, 0, 0, 0, 0, 0, 0, 1, 0
    0, 0, 0, 0, 0, 0, 0, 0, 0, 1
*/

Kullanabileceğiniz create_task eşdeğer işlemi oluşturmak için işlev.

auto create_identity_matrix = create_task([]
{
    array<array<int, 10>, 10> matrix;
    int row = 0;
    for_each(begin(matrix), end(matrix), [&row](array<int, 10>& matrixRow) 
    {
        fill(begin(matrixRow), end(matrixRow), 0);
        matrixRow[row] = 1;
        row++;
    });
    return matrix;
});

Görev yürütme sırasında bir özel durum, çalışma zamanı bu durum sonraki çağrısında sýralar task::get veya task::wait, ya da görev tabanlı devamı. Görev özel durum işleme mekanizması hakkında daha fazla bilgi için bkz: Özel durum işleme eşzamanlılık çalışma zamanında.

Kullanan bir örnek için task, concurrency::task_completion_event, iptalin bkz: İzlenecek yol: Görevleri ve xml http isteği (IXHR2) kullanarak bağlanma. ( task_completion_event Sınıfı bu belgenin sonraki bölümlerinde açıklanmıştır.)

İpucu

Belirli görevlere ayrıntıları öğrenmek için Windows Mağazası apps, bkz: Asynchronous programming in C++ ve Windows Mağazası Uygulamaları için C++ Uygulamasında Zaman Uyumsuz İşlemler Oluşturma.

Top

Devamı görevleri

Zaman uyumsuz programlamada, ikinci bir işlemi çağırmak ve veri iletmektir tamamlandığında, bir zaman uyumsuz işlem için yaygın olarak. Geleneksel olarak, bu geri çağrı yöntemleri kullanılarak yapılır. Eşzamanlılık çalışma zamanı aynı işlevleri tarafından sağlanan devamı görevleri. (Yalnızca bir devamı da bilinir) bir devamı olarak bilinen başka bir görev tarafından başlatılan zaman uyumsuz bir görev görevdir antecedent, antecedent tamamlandığında. Continuations kullanarak şunları yapabilirsiniz:

  • Verileri antecedent devamı geçirir.

  • Devamı çağrılan veya çağrılan değil hangi koşullarda kesin koşulları belirtin.

  • Bir devamı başlamadan önce ya da cooperatively çalışırken iptal edin.

  • Devamı zamanlanmış nasıl hakkında ipuçları sağlar. (Bu çözümün uygulandığı Windows Mağazası yalnızca uygulamalar. Daha fazla bilgi için, bkz. Windows Mağazası Uygulamaları için C++ Uygulamasında Zaman Uyumsuz İşlemler Oluşturma.)

  • Aynı antecedent gelen birden çok continuations çağırır.

  • Tüm ya da birden fazla antecedents birini tamamladıktan sonra bir devamı çağırır.

  • Continuations birbiri ardına herhangi bir uzunlukta zincir.

  • Bir devamı antecedent tarafından atılan özel durumlarý iþlemek için kullanın.

Bu özellikler ilk görev tamamlandığında, bir veya daha fazla görevi yürütmek etkinleştirin. Örneğin, ilk görev, diskten okuduktan sonra bir dosyayı sıkıştırır devamı oluşturabilirsiniz.

Aşağıdaki örnek kullanmak için eskisinin değiştirir concurrency::task::then kullanılabilir olduğunda, öncül görev değerinin yazdıran devamı zamanlamak için yöntem.

// basic-continuation.cpp
// compile with: /EHsc
#include <ppltasks.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
    auto t = create_task([]() -> int
    {
        return 42;
    });

    t.then([](int result)
    {
        wcout << result << endl;
    }).wait();

    // Alternatively, you can chain the tasks directly and
    // eliminate the local variable.
    /*create_task([]() -> int
    {
        return 42;
    }).then([](int result)
    {
        wcout << result << endl;
    }).wait();*/
}

/* Output:
    42
*/

Zincir ve herhangi bir uzunlukta görevler iç içe aktarabilirsiniz. Bir görevin birden fazla continuations da sahip olabilirsiniz. Aşağıdaki örnekte, üç kez önceki görev değerini artıran bir temel devamı zinciri gösterilmektedir.

// continuation-chain.cpp
// compile with: /EHsc
#include <ppltasks.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
    auto t = create_task([]() -> int
    { 
        return 0;
    });

    // Create a lambda that increments its input value.
    auto increment = [](int n) { return n + 1; };

    // Run a chain of continuations and print the result.
    int result = t.then(increment).then(increment).then(increment).get();
    wcout << result << endl;
}

/* Output:
    3
*/

Bir devamı da başka bir göreve iade edebilirsiniz. Hiçbir iptali ise, bu görevi izleyen devamı önce yürütüldü. Bu teknik olarak bilinen zaman uyumsuz unwrapping. Arka planda ek iş yapmak istiyorsanız, ancak geçerli iş parçacığı engellemek için geçerli görev istemiyorsanız, zaman uyumsuz unwrapping yararlı olur. (Bu, sık kullanılan bir Windows Mağazası continuations çalıştırdığı UI iş parçacığında apps). Aşağıdaki örnek, üç görevleri gösterir. İlk görev önce devamı görevi çalıştırma başka bir görev verir.

// async-unwrapping.cpp
// compile with: /EHsc
#include <ppltasks.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
    auto t = create_task([]()
    {
        wcout << L"Task A" << endl;

        // Create an inner task that runs before any continuation
        // of the outer task.
        return create_task([]()
        {
            wcout << L"Task B" << endl;
        });
    });

    // Run and wait for a continuation of the outer task.
    t.then([]()
    {
        wcout << L"Task C" << endl;
    }).wait();
}

/* Output:
    Task A
    Task B
    Task C
*/

Önemli

Ne zaman bir devamı olarak bir görev verir iç içe görev türü N, ortaya çıkan görev türüne sahip Nyerine task<N>ve iç içe görev tamamlandığında tamamlar.Diğer bir deyişle, devamı unwrapping iç içe görevini gerçekleştirir.

Top

Değere göre görev tabanlı Continuations karşı

Verilen bir task , dönüş türü olan nesne T, türde bir değer sağlayabilir T veya task<T> devamı işler için. Tür alır devamı T olarak bilinen bir değerine göre devamı. Öncül görev hatasız tamamlayıp iptal değerine göre devamı çalıştırılmak üzere planlanmıştır. Tür alır devamı task<T> onun parametresi olarak bilinen bir görev tabanlı devamı. Öncül görevin sona erdiğinde, hatta ne zaman öncül görev iptal edilir veya bir istisna atar görev tabanlı devamı her zaman çalıştırılmak üzere planlanmıştır. Ardından çağrı task::get öncül görevin sonucu elde etmek için. Öncül görev iptal, task::get atan concurrency::task_canceled. Öncül görevin özel durum gönderdi, task::get bu durum rethrows. Görev tabanlı devamı, öncül görev iptal edildiğinde iptal edildi olarak işaretlenmemiş.

Top

Görevler oluşturma

Bu bölümde açıklanmaktadır concurrency::when_all ve concurrency::when_any yardımcı olabilecek işlevler ortak desenleri uygulamak için birden fazla görev oluşturun.

Dd492427.collapse_all(tr-tr,VS.110).gifWhen_all işlevi

when_all İşlevi bir dizi görevi tamamladıktan sonra tamamlar bir görev oluşturur. Bu işlevi döndüren bir std::vector sonuç kümesindeki her görevin içeren nesne. Aşağıdaki temel örnek when_all üç görev tamamlanma gösteren bir görev oluşturmak için.

// join-tasks.cpp
// compile with: /EHsc
#include <ppltasks.h>
#include <array>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
    // Start multiple tasks.
    array<task<void>, 3> tasks = 
    {
        create_task([] { wcout << L"Hello from taskA." << endl; }),
        create_task([] { wcout << L"Hello from taskB." << endl; }),
        create_task([] { wcout << L"Hello from taskC." << endl; })
    };

    auto joinTask = when_all(begin(tasks), end(tasks));

    // Print a message from the joining thread.
    wcout << L"Hello from the joining thread." << endl;

    // Wait for the tasks to finish.
    joinTask.wait();
}

/* Sample output:
    Hello from the joining thread.
    Hello from taskA.
    Hello from taskC.
    Hello from taskB.
*/

Not

Geçişi için görevleri when_all tek tip olması gerekir.Diğer bir deyişle, bunların tümü aynı türde döndürmesi gerekir.

Ayrıca && bir dizi görevi tamamladıktan sonra aşağıdaki örnekte gösterildiği gibi tamamlar bir görev oluşturmak için sözdizimi.

auto t = t1 && t2; // same as when_all

Devamı ile birlikte kullanmak için ortak olan when_all bir dizi görevi tamamladıktan sonra bir eylem gerçekleştirme. Aşağıdaki örnek üç görev toplamını yazdırmak için eskisinin değiştirir her üreten bir int sonucu.

// Start multiple tasks.
array<task<int>, 3> tasks =
{
    create_task([]() -> int { return 88; }),
    create_task([]() -> int { return 42; }),
    create_task([]() -> int { return 99; })
};

auto joinTask = when_all(begin(tasks), end(tasks)).then([](vector<int> results)
{
    wcout << L"The sum is " 
          << accumulate(begin(results), end(results), 0)
          << L'.' << endl;
});

// Print a message from the joining thread.
wcout << L"Hello from the joining thread." << endl;

// Wait for the tasks to finish.
joinTask.wait();

/* Output:
    Hello from the joining thread.
    The sum is 229.
*/

Bu örnekte, aynı zamanda belirtebileceğiniz task<vector<int>> görev tabanlı devamı üretmek için.

Uyarı

Bir dizi görevi de herhangi bir görevi iptal edilir ya da bir istisna atar when_all hemen tamamlar ve tamamlamak kalan görevler için beklemez.Bir özel durum oluşursa, aradığınızda, çalışma zamanı özel durumu rethrows task::get veya task::wait , task nesnesinin when_all döndürür.Birden fazla görev oluşturursa, çalışma zamanı, bunlardan birini seçer.Bu nedenle, tek bir özel durum oluşturursa, tüm görevleri tamamlamak bekleyin emin olun.

Top

Dd492427.collapse_all(tr-tr,VS.110).gifWhen_any işlevi

when_any İşlevi, görevler kümesi ilk görev tamamlandığında tamamlayan bir görev oluşturur. Bu işlevi döndüren bir std::pair sonucu, tamamlanmış bir görevi ve o görev kümesi dizini içeren nesne.

when_any İşlev, özellikle aşağıdaki senaryolarda kullanışlıdır:

  • Yedek işlem. Algoritma veya çeşitli yollarla gerçekleştirilen işlem göz önünde bulundurun. Kullanabileceğiniz when_any işlevi tamamlanmadan önce işlemi seçin ve kalan işlemleri iptal etmek için.

  • Aralanmış işlemleri. Birden çok işlemi başlamadan tüm bitiş kullanın ve gerekir, when_any her işlemi bittiği gibi sonuçları işlemek için işlevi. Bir işlemi sona erdikten sonra bir veya daha fazla ek görevler başlatabilirsiniz.

  • Daraltılmış işlemleri. Kullanabileceğiniz when_any eş zamanlı operasyonlar sayısını sınırlayarak önceki senaryoda genişletmek için işlevi.

  • Süresi dolan işlemleri. Kullanabileceğiniz when_any bir veya daha fazla görevi sona erdikten sonra belirli bir süre görev arasındaki seçmek için işlevi.

Olduğu gibi when_all, sahip devamı kullanmak için ortak olan when_any bir dizi görevi ilk bitirdikten sonra eylemi gerçekleştirmek için. Aşağıdaki temel örnek when_any ilk üç diğer görevler tamamlandığında tamamlayan bir görev oluşturmak için.

// select-task.cpp
// compile with: /EHsc
#include <ppltasks.h>
#include <array>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
    // Start multiple tasks.
    array<task<int>, 3> tasks = {
        create_task([]() -> int { return 88; }),
        create_task([]() -> int { return 42; }),
        create_task([]() -> int { return 99; })
    };

    // Select the first to finish.
    when_any(begin(tasks), end(tasks)).then([](pair<int, size_t> result)
    {
        wcout << "First task to finish returns "
              << result.first
              << L" and has index "
              << result.second
              << L'.' << endl;
    }).wait();
}

/* Sample output:
    First task to finish returns 42 and has index 1.
*/

Bu örnekte, aynı zamanda belirtebileceğiniz task<pair<int, size_t>> görev tabanlı devamı üretmek için.

Not

Olduğu gibi when_all, geçişi için görevleri when_any tümü aynı türde döndürmesi gerekir.

Ayrıca || bir dizi görevi de ilk görevi tamamlandıktan sonra aşağıdaki örnekte gösterildiği gibi tamamlar bir görev oluşturmak için sözdizimi.

auto t = t1 || t2; // same as when_any

Top

Geciken görev yürütme

Bazen bir koşul sağlanırsa kadar bir görevin yürütülmesini gecikme ya da harici bir olaya yanıt olarak bir görevi başlatmak için gereklidir. Örneğin, zaman uyumsuz programlamada, bir g/Ç tamamlanma olayına yanıt olarak bir görevi başlatmak gerekebilir.

Bunu gerçekleştirmenin iki yolu bir devamı kullanın veya bir görevi başlatmak ve bir olayı görevin çalışma işlevi içinde bekleyin üzeresiniz. Ancak, durumlar vardır, aşağıdaki tekniklerden birini kullanmak mümkün değildir. Örneğin, bir devamı oluşturmak için öncül görev olmalıdır. Ancak, öncül görev yoksa, oluşturabileceğiniz bir görev tamamlanma olay ve kullanılabilir olduğunda sonraki öncül görevin tamamlanma olay zincir. Buna ek olarak, bir iş parçacığı bekleyen görev de engellediği için zaman uyumsuz işlemi tamamlandığında çalışmayı gerçekleştirmek için görev tamamlama olaylarına kullanın ve bu nedenle bir iş parçacığının serbest.

Concurrency::task_completion_event sınıfı bu tür görevleri oluşumunu tutulmasını basitleştirmeye yardımcı olur. Gibi task class, type parametresi T görevi tarafından üretilen sonuç türüdür. Bu tür olabilir void , görev bir değer döndürmez. Tkullanamazsınız const değiştiricisi. Genellikle, bir task_completion_event nesne için iş parçacığı veya değeri kullanılabilir duruma geldiğinde sinyalini verecek görev sağlanır. Aynı anda bir veya daha fazla görev o olay dinleyicileri olarak ayarlanır. Olay ayarladığınızda, dinleyici görevleri tamamlamak ve kendi continuations çalışacak şekilde zamanlanır.

Kullanan bir örnek için task_completion_event bir gecikmeden sonra tamamlar bir görevi uygulamak için bkz: Nasıl yapılır: bir gecikmeden sonra tamamlar bir görev oluşturma.

Top

Görev Grupları

A görev grubu görevleri topluluğu düzenler. Görev grupları çalışma çalarak sıra oturum açma görevlerini itin. Zamanlayıcı görevler bu sıradan kaldırır ve kullanılabilir bilgi işlem kaynaklarını yürütür. Görevleri görev grubuna ekledikten sonra son veya henüz başlatılmamış görevleri iptal etmek tüm görevler için bekleyebilir.

ppl kullanan concurrency::task_group ve concurrency::structured_task_group görev gruplarını göstermek için sınıflar ve concurrency::task_handle Bu gruplar halinde çalışacak görevleri temsil eden sınıf. task_handle Class işini gerçekleştiren kod içinde saklar. Gibi task sınıfı, iş işlevi lambda işlevi, işlev işaretçisi veya işlev nesne şeklinde gelir. Genellikle çalışmak gerekmez task_handle doğrudan nesneleri. Bunun yerine, bir görev grubu iş işlevlerini geçmesi ve görev grubu oluşturur ve yönetir task_handle nesneler.

ppl Görev grupları bu iki kategoriye ayırır: yapılandırılmamış Görev grupları ve yapılı görev grupları. ppl kullanan task_group yapılandırılmamış Görev grupları temsil eden sınıf ve structured_task_group yapılı görev grupları temsil eden sınıf.

Önemli

ppl de tanımlayan concurrency::parallel_invoke kullandığı algoritma structured_task_group paralel olarak bir dizi görevi yürütmek için sınıf.Çünkü parallel_invoke algoritması daha Sözün bir sözdizimine sahip, yerine kullanmanızı öneririz structured_task_group class taramasını.Konuyu Paralel algoritmalar açıklar parallel_invoke daha ayrıntılı.

Use parallel_invoke ne zaman aynı anda çalıştırmak istediğinizde birkaç bağımsız görev varsa ve devam etmeden önce bitirmek tüm görevler için beklemeniz gerekir. Bu teknik, genellikle olarak adlandırılır çatalı ve JOIN paralellik. Use task_group ne zaman aynı anda çalıştırmak istediğinizde birkaç bağımsız görevler vardır, ancak daha sonraki bir zamanda tamamlamak görevler için beklemek istiyor. Örneğin, görevler ekleyebileceğiniz bir task_group object ve görevleri baþka bir iþlev içinde ya da başka bir iş parçacığının bitmesini bekleyin.

Görev grupları iptali kavramını destekler. İptali genel işlemi iptal etmek istediğiniz tüm etkin görevleri için sinyal olanak tanır. İptali başlatılmasını henüz başlatmamışlarsa görevleri de engeller. İptal etme hakkında daha fazla bilgi için bkz: ppl iptali.

Zamanı da görevden istisna ve bitirmek ilişkili görev grubu için bekleyin, bu özel durumunu işlemesi olanak veren bir özel durum işleme modeli sağlar. Bu özel durum işleme modeli hakkında daha fazla bilgi için bkz: Özel durum işleme eşzamanlılık çalışma zamanında.

Top

Structured_task_group task_group karşılaştırması

Sizin kullanmanızı öneririz, ancak task_group veya parallel_invoke yerine structured_task_group sınıfı, kullanmak istediğiniz durumlarda structured_task_group, örneğin, ne zaman yazdığınız bir paralel algoritması değişken bir dizi görevi gerçekleştirir veya iptali için destek gerektirir. Bu balıkta arasındaki farklılıkları task_group ve structured_task_group sınıfları.

task_group İş parçacığı için güvenli bir sınıftır. Bu nedenle görevler ekleyebileceğiniz bir task_group nesne birden çok iş parçacığı bekleyin veya iptal bir task_group birden çok iş parçacığı nesnesi. İnşaat ve imha, bir structured_task_group nesne sözlü aynı kapsam içinde gerçekleşmesi gerekir. Buna ek olarak, tüm işlemler bir structured_task_group nesne aynı iş parçacığı üzerinde gerçekleşmesi gerekir. Bu kuralın istisnası concurrency::structured_task_group::cancel ve concurrency::structured_task_group::is_canceling yöntemleri. Alt görev üst görev grubu iptal edebilir veya herhangi bir zamanda iptali denetlemek için bu yöntemleri çağırabilir.

Ek görevleri çalıştırmak bir task_group , çağrısından sonra nesne concurrency::task_group::wait veya concurrency::task_group::run_and_wait yöntemi. Size ek görevler tam tersine, çalışamaz bir structured_task_group , çağrısından sonra nesne concurrency::structured_task_group::wait veya concurrency::structured_task_group::run_and_wait yöntemleri.

Çünkü structured_task_group sınıfı iş parçacıkları arasında eşitleme değil, yükü daha az yürütme olan task_group sınıfı. Bu nedenle, sorun, gerektirmiyorsa birden çok iş parçacığı işten zamanlamak ve kullanamazsınız parallel_invoke algoritması, structured_task_group sınıfı daha iyi performanslı kod yazmanıza yardımcı olabilir.

Birini kullanırsanız, structured_task_group içinde başka bir nesne structured_task_group nesnesi, iç nesne bitmesi gereken tarih ve dış nesne tamamlanmadan önce bozdu. task_group Class dış Grup tamamlanmadan önce bitirmek, iç içe Görev grupları gerektirmez.

Yapılandırılmamış Görev grupları ve yapılı görev grupları görev tutamaçlı farklı şekillerde çalışır. İş işlevlerini doğrudan geçmesi bir task_group nesne; task_group nesnesi oluşturun ve sizin için görev tutamacı yönetmek. structured_task_group Sınıf gerektirir, yönetmek bir task_handle her görev için nesne. Her task_handle nesnesi olmalıdır kalır, onunla ilişkili yaşam süresi geçerli structured_task_group nesnesi. Use concurrency::make_task işlevi oluşturmak için bir task_handle nesne aşağıdaki basit örnekte gösterildiği gibi:

// make-task-structure.cpp
// compile with: /EHsc
#include <ppl.h>

using namespace concurrency;

int wmain()
{
   // Use the make_task function to define several tasks.
   auto task1 = make_task([] { /*TODO: Define the task body.*/ });
   auto task2 = make_task([] { /*TODO: Define the task body.*/ });
   auto task3 = make_task([] { /*TODO: Define the task body.*/ });

   // Create a structured task group and run the tasks concurrently.

   structured_task_group tasks;

   tasks.run(task1);
   tasks.run(task2);
   tasks.run_and_wait(task3);
}

Görev işleme görevlerini sayılarda olduğu durumlarda yönetmek için bir yığın ayırma yordam gibi kullanmak _malloca ya da konteyner sınıfı gibi std::vector.

Her ikisi de task_group ve structured_task_group iptali destekler. İptal etme hakkında daha fazla bilgi için bkz: ppl iptali.

Top

Örnek

Aşağıdaki basit örnekte Görev grupları ile çalışmak nasıl gösterir. Bu örnek parallel_invoke görevleri aynı anda iki gerçekleştirmek için algoritma. Her görev ekler alt görevler için bir task_group nesnesi. Dikkat task_group sınıfı, birden çok görevi görevleri aynı anda eklemek olanak tanır.

// using-task-groups.cpp
// compile with: /EHsc
#include <ppl.h>
#include <sstream>
#include <iostream>

using namespace concurrency;
using namespace std;

// Prints a message to the console.
template<typename T>
void print_message(T t)
{
   wstringstream ss;
   ss << L"Message from task: " << t << endl;
   wcout << ss.str(); 
}

int wmain()
{  
   // A task_group object that can be used from multiple threads.
   task_group tasks;

   // Concurrently add several tasks to the task_group object.
   parallel_invoke(
      [&] {
         // Add a few tasks to the task_group object.
         tasks.run([] { print_message(L"Hello"); });
         tasks.run([] { print_message(42); });
      },
      [&] {
         // Add one additional task to the task_group object.
         tasks.run([] { print_message(3.14); });
      }
   );

   // Wait for all tasks to finish.
   tasks.wait();
}

Bu örnek için bir örnek çıktı verilmiştir:

Message from task: Hello
Message from task: 3.14
Message from task: 42

Çünkü parallel_invoke algoritması görevleri aynı anda çalıştırıldığında, çıktı iletileri sırası değişir.

Nasıl kullanacağınızı gösteren tam örnek için parallel_invoke , algoritması bkz: Nasıl yapılır: paralel sıralama rutin yazmak için parallel_invoke kullanın ve Nasıl yapılır: parallel_invoke paralel işlemleri yürütmek için kullanın.. Kullandığı tam bir örnek için task_group zaman uyumsuz vadeli işlem uygulamak için bkz: sınıf Adım adım işlem aşamaları: Vadeli işlem uygulama.

Top

Güçlü programlama

İptali ve görevleri, Görev grupları ve paralel algoritmalar kullandığınızda özel durum işleme rolünü anladığınızdan emin olun. Örneğin, paralel iş ağacında iptal edilirse bir görevi alt görevlere çalışmasını engeller. Alt görevlerden birini önemli bir kaynağı boşaltmayı gibi uygulamanıza bir işlem yapar, bu sorunlara neden olabilir. Buna ek olarak, alt görevi bir özel durum oluşturursa, o özel bir nesne yıkıcısının yaymak ve uygulamanızda tanımsız davranışlara neden. Bu noktaları gösterilmektedir bir örnek için bkz: Understand how Cancellation and Exception Handling Affect Object Destruction paralel Desenler kitaplığının belge içinde en iyi yöntemler bölümündeki. İptali ve ppl de özel durum işleme modelleri hakkında daha fazla bilgi için bkz: ppl iptali ve Özel durum işleme eşzamanlılık çalışma zamanında.

Top

İlgili Konular

Başlık

Tanımlama

Nasıl yapılır: paralel sıralama rutin yazmak için parallel_invoke kullanın

Nasıl kullanılacağını gösteren parallel_invoke bitonic sıralama algoritmasını performansını artırmak için algoritma.

Nasıl yapılır: parallel_invoke paralel işlemleri yürütmek için kullanın.

Nasıl kullanılacağını gösteren parallel_invoke paylaşılan veri kaynağı üzerinde birden çok işlemi gerçekleştiren bir program performansını algoritması.

Nasıl yapılır: bir gecikmeden sonra tamamlar bir görev oluşturma

Nasıl kullanılacağını gösteren task, cancellation_token_source, cancellation_token, ve task_completion_event bir gecikmeden sonra tamamlar bir görev oluşturmak için sınıflar.

Adım adım işlem aşamaları: Vadeli işlem uygulama

Daha fazla yapan varolan işlevsellik eşzamanlılık çalışma zamanında bir şey birleştirmek gösterilmiştir.

Paralel Desenler kitaplığının (ppl)

Eş zamanlı uygulamalar geliştirmek için onun bir programlama modeli sağlar ppl açıklar.

Reference

Sınıf (eşzamanlılık Runtime) görev

task_completion_event sınıfı

when_all işlevi

when_any işlevi

task_group sınıfı

parallel_invoke işlevi

structured_task_group sınıfı