2015-01-30 4 views
0

하나의 태스크가 변수에 할당하고 다음 태스크가 해당 변수에서 읽는 람다 식을 사용하는 연속 체인이 있습니다. Microsoft suggests using a shared_ptr to wrap the variable even when the variable is a reference-counted handle (^). 람다 식으로 값으로 캡처 할 때 참조 카운트 핸들이 참조 카운트를 증가시키지 않습니까? 그렇다면 왜 shared_ptr과 함께 참조 계산 핸들을 래핑 할 필요가 있습니까?연속 체인에서 공유 포인터가 필요합니까?

답변

3

문서는 만드는 분명히 연속 체인 에서

하나의 작업 변수에 할당하고, 다른 작업 읽기 그들이 어디에 대해 우려하고있는 경우가 그들이다 것을 그 변수

(강조는 광산입니다.) 이것은 객체 의 생애이 아니라 객체 신분의 질문입니다.

decoder 변수에 세심한주의를 기울이고 상기 Hilo project에서 예를 타고이다 (이는 shared_ptr<BitmapDecoder^>)

가 다중 연속 요청에서 요구되기 때문에 decoder 변수 우선, 연속 요청의 외부 정의
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; 
    }); 
} 

. 이 시점에서 값은 null입니다. 그것은 두 번째 연속 내에서 획득되고 설정되며, 그 객체의 속성 (PixelWidth 등)이 네 번째 연속 내에서 사용됩니다.

는 변경이 다시 초기 핸들에 반영 할 수 없기 때문에 대신, 변화가 이후의 연속성을 전파하지 않을, decoderBitmapDecoder^로 정의 할 수 있습니다 nullptr로 설정 한 다음 그것을 두 번째 지속 내의 값을 할당 할 수 있었 (람다는 본질적으로 메모리 주소 0x00000000을 복사하는 핸들 복사본을 만들었습니다.)

원래 버전 (및 후속 참조)을 업데이트하려면 추가 간접 참조 (예 : BitmapDecoder^*)가 필요합니다. shared_ptr<BitmapDecoder^>은 그러한 간접 참조 중 하나이며, 원시 포인터와 달리 포인터의 수명을 관리 할 필요가 없다는 점에서 유용한 것입니다. 따라서 문서에서 권장됩니다.

예를 들어 TextBlock^을 내 속편 외부에 만들고 첫 번째 연속에서 일부 속성을 설정하고 후속 연속에서 다른 속성을 읽는 경우와 같이 Object^을 캡처하는 것으로 충분할 수도 있습니다. 이 경우 모든 핸들이 동일한 기본 오브젝트를 참조하며 연속은 오브젝트 자체의 ID를 겹쳐 쓰려고 시도하지 않습니다. (그러나 처음에 언급했듯이 이것은 문서가 참조하고있는 사용 사례는 아닙니다.)