2015-01-30 3 views
0

У меня есть цепочка продолжения с использованием лямбда-выражений, где одна задача назначает переменную, а следующая задача считывается из этой переменной. Microsoft suggests using a shared_ptr to wrap the variable even when the variable is a reference-counted handle (^). Не обработал ли счетчик отсчета счетчик ссылок при захвате значением значением лямбда? Почему тогда необходимо обернуть обработанный ссылкой счетчик с помощью shared_ptr?Нужны ли общие указатели в цепях продолжения?

ответ

3

документация становится ясно, что дела, они обеспокоены являются те, где

одна задача в продолжении цепи присваивает переменной, и другая задача читает эту переменную

(Акцент мой.) Это не вопрос объекта life life, а вопрос об объекте identity.

Возьмите этот пример из Hilo project, обращая особое внимание на переменную decoder (который является shared_ptr<BitmapDecoder^>):

task<InMemoryRandomAccessStream^> ThumbnailGenerator::CreateThumbnailFromPictureFileAsync(
    StorageFile^ sourceFile, 
    unsigned int thumbSize) 
{ 
    (void)thumbSize; // Unused parameter 
    auto decoder = make_shared<BitmapDecoder^>(nullptr); 
    auto pixelProvider = make_shared<PixelDataProvider^>(nullptr); 
    auto resizedImageStream = ref new InMemoryRandomAccessStream(); 
    auto createThumbnail = create_task(
     sourceFile->GetThumbnailAsync(
     ThumbnailMode::PicturesView, 
     ThumbnailSize)); 

    return createThumbnail.then([](StorageItemThumbnail^ thumbnail) 
    { 
     IRandomAccessStream^ imageFileStream = 
      static_cast<IRandomAccessStream^>(thumbnail); 

     return BitmapDecoder::CreateAsync(imageFileStream); 

    }).then([decoder](BitmapDecoder^ createdDecoder) 
    { 
     (*decoder) = createdDecoder; 
     return createdDecoder->GetPixelDataAsync( 
      BitmapPixelFormat::Rgba8, 
      BitmapAlphaMode::Straight, 
      ref new BitmapTransform(), 
      ExifOrientationMode::IgnoreExifOrientation, 
      ColorManagementMode::ColorManageToSRgb); 

    }).then([pixelProvider, resizedImageStream](PixelDataProvider^ provider) 
    { 
     (*pixelProvider) = provider; 
     return BitmapEncoder::CreateAsync(
      BitmapEncoder::JpegEncoderId, 
      resizedImageStream); 

    }).then([pixelProvider, decoder](BitmapEncoder^ createdEncoder) 
    { 
     createdEncoder->SetPixelData(BitmapPixelFormat::Rgba8, 
      BitmapAlphaMode::Straight, 
      (*decoder)->PixelWidth, 
      (*decoder)->PixelHeight, 
      (*decoder)->DpiX, 
      (*decoder)->DpiY, 
      (*pixelProvider)->DetachPixelData()); 
     return createdEncoder->FlushAsync(); 

    }).then([resizedImageStream] 
    { 
     resizedImageStream->Seek(0); 
     return resizedImageStream; 
    }); 
} 

Переменная decoder впервые определена вне продолжений, так как он необходим в нескольких продолжений , В этот момент его значение равно нулю. Он получен и установлен во втором продолжении, и свойства этого объекта (PixelWidth и т. Д.) Используются в четвертом продолжении.

Были ли вы, чтобы вместо этого decoder быть определены как BitmapDecoder^, установите его в nullptr, а затем присвоить ему значение в пределах второго продолжения, это изменение не будет распространяться на последующие продолжений, потому что изменение не может отражаться обратно к исходной ручке (лямбда сделала копию дескриптора, по существу копируя адрес памяти 0x00000000).

Для обновления исходной версии (и последующих ссылок) вам потребуется дополнительное косвенное направление (например, BitmapDecoder^*). A shared_ptr<BitmapDecoder^> - одно из таких направлений и полезно, поскольку вам не нужно управлять временем жизни указателя, в отличие от необработанного указателя, поэтому рекомендуется в документации.

Есть и другие случаи, когда захват Object^ было бы достаточно, если я создал TextBlock^ вне моего продолжения и установить некоторые свойства этого в первом продолжении и прочитать некоторые другие свойства в последующем продолжении. В этом случае все дескрипторы относятся к одному и тому же базовому объекту, и никакое продолжение не пытается переписать личность самого объекта. (Однако, как первоначально упоминалось, это не тот случай, о котором идет речь в документации.)

 Смежные вопросы

  • Нет связанных вопросов^_^