> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# XGameSaveReadBlobDataAsync

> XGameSaveReadBlobDataAsync

# XGameSaveReadBlobDataAsync

**XGameSaveContainer** 에서 [XGameSaveBlob](/reference/system/xgamesave/structs/xgamesaveblob) 데이터를 비동기적으로 읽습니다.

## 구문

```cpp theme={null}
HRESULT XGameSaveReadBlobDataAsync(  
         XGameSaveContainerHandle container,  
         const char** blobNames,  
         uint32_t countOfBlobs,  
         XAsyncBlock* async  
)  
```

### 매개 변수

*container*   \_In\_\
형식: XGameSaveContainerHandle

게임 저장 Blob 데이터를 담고 있는 컨테이너입니다.

*blobNames*   \_In\_opt\_z\_count\_(countOfBlobs)\
형식: char\*\*

[XGameSaveBlob](/reference/system/xgamesave/structs/xgamesaveblob) 이름을 나타내는 문자열 배열에 대한 포인터입니다.

*countOfBlobs*   \_In\_\
형식: uint32\_t

읽을 Blob의 수입니다.

*async*   \_In\_\
형식: [XAsyncBlock\*](/reference/system/xasync/structs/xasyncblock)

**XGameSaveReadBlobDataAsync** 호출에 대한 컨텍스트와 콜백 함수를 포함하는 AsyncBlock입니다.

### 반환값

형식: HRESULT

함수 결과입니다.

## 설명

결과와 데이터는 [XGameSaveReadBlobDataResult](/reference/system/xgamesave/functions/xgamesavereadblobdataresult) 함수에서 캡처됩니다. [XGameSaveReadBlobDataResult](/reference/system/xgamesave/functions/xgamesavereadblobdataresult)는 컨테이너의 Blob 수와 Blob 데이터 자체를 반환합니다. 이 함수에는 [XGameSaveReadBlobData](/reference/system/xgamesave/functions/xgamesavereadblobdata)라는 동기식 버전이 있습니다.

<a id="example" />

```cpp theme={null}
// ASYNC Read - can be kicked off from a time sensitive thread 
//              actual work and completion will be scheduled based upon  
//              the configuration of the async_queue tied to the XAsyncBlock 
void Sample::_ReadContainerBlobsAsync(const XGameSaveContainerInfo* container) 
{ 
    const char* blobNames[] = { 
        "WorldState", 
        "PlayerState", 
        "PlayerInventory" 
    }; 
  
    struct LoadContext 
    { 
        LoadContext(Sample* s) : container(nullptr), self(s) {} 
        ~LoadContext() 
        { 
            XGameSaveCloseContainer(container); 
        } 
        XAsyncBlock async; 
        XGameSaveContainerHandle container; 
        Sample* self; 
    }; 
    HRESULT hr; 
    LoadContext* loadContext = new LoadContext(this); 
    if (loadContext == nullptr) 
    { 
        hr = E_OUTOFMEMORY; 
    } 
  
    auto completionCallback = [](XAsyncBlock* async) 
    { 
        auto ctx = reinterpret_cast<LoadContext*>(async->context); 
        auto self = ctx->self; 
        size_t allocatedSize; 
        XGameSaveBlob* blobData = nullptr; 
        uint32_t blobCount = 0; 
  
        HRESULT hr = GetAsyncStatus(async, false); 
  
        if (SUCCEEDED(hr)) 
        { 
            // use local wrapper for GetAsyncResultSize to give strongly typed alloc 
            XGameSaveBlob* blobData = _AllocAsyncResult<XGameSaveBlob>(async, &allocatedSize); 
            if (blobData == nullptr) 
            { 
                hr = E_OUTOFMEMORY; 
            } 
        } 
  
        if (SUCCEEDED(hr)) 
        { 
            // now that we have allocated the required buffers 
            // ask XGameSave to populate them 
            hr = XGameSaveReadBlobDataResult(async, allocatedSize, blobData, &blobCount); 
        } 
        if (SUCCEEDED(hr)) 
        { 
            if (blobCount == _countof(blobNames)) 
            { 
                for (uint32_t i = 0; i < blobCount; i++) 
                { 
                    XGameSaveBlob* currentBlob = blobData + i; 
                    if (strcmp(currentBlob->info.name, "WorldState") == 0) 
                    { 
                        hr = self->_LoadSaveBlob(currentBlob, self->_worldState); 
                    } 
                    else if (strcmp(currentBlob->info.name, "PlayerState") == 0) 
                    { 
                        hr = self->_LoadSaveBlob(currentBlob, self->_playerState); 
                    } 
                    else if (strcmp(currentBlob->info.name, "PlayerInventory") == 0) 
                    { 
                        hr = self->_LoadSaveBlob(currentBlob, self->_playerInventory); 
                    } 
                    if (FAILED(hr)) 
                    { 
                        break; 
                    } 
                } 
            } 
            else 
            { 
                // what containers are missing? Can we get by without XXX? 
                hr = E_UNEXPECTED; 
            } 
        } 
  
        self->_HandleContainerBlobErrors(hr); 
  
        if (blobData != nullptr) 
        { 
            // we own the buffer so better kill it 
            free(blobData); 
        } 
        // be sure to clear this since it will be no longer valid after we exit 
        self->_asyncLoad = nullptr; 
        // kill the temp context tracking the async op 
        delete ctx; 
    }; 
  
    if (SUCCEEDED(hr)) 
    { 
        loadContext->async.context = loadContext; 
        // set the XTaskQueueHandle so the completion will be done on our thread 
        // and then we can allocate the larger buffers with less lock contention 
        loadContext->async.queue = _asyncCompleteQueue; 
        loadContext->async.callback = completionCallback; 
    } 
  
    hr = XGameSaveCreateContainer(_provider, container->name, &loadContext->container); 
    if (SUCCEEDED(hr)) 
    { 
        hr = XGameSaveReadBlobDataAsync(loadContext->container, blobNames, _countof(blobNames), &loadContext->async); 
    } 
    if (SUCCEEDED(hr)) 
    { 
        // keep a reference to this so we can Cancel later if needed 
        _asyncLoad = &loadContext->async;  
        // hand over ownership to the async callback 
        loadContext = nullptr;  
    } 
  
    if (loadContext) 
    { 
        delete loadContext; 
    } 
    if (FAILED(hr)) 
    { 
        _HandleContainerBlobErrors(hr); 
    } 
} 
 
// Allocate a strongly typed portion from an Async Result 
template<typename T> 
static T* _AllocAsyncResult(XAsyncBlock* async, size_t* allocatedSize) 
{ 
    *allocatedSize = 0; 
    size_t allocSize = 0; 
    HRESULT hr = XAsyncGetResultSize(async, &allocSize); 
    if (SUCCEEDED(hr) && allocSize > 0) 
    { 
        *allocatedSize = allocSize; 
        return reinterpret_cast<T*>(malloc(allocSize)); 
    } 
    return nullptr; 
} 
  
/*static*/ 
DWORD Sample::_CompleteThreadProc(PVOID context) 
{ 
    auto self = reinterpret_cast<Sample*>(context); 
  
    while (DWORD wait = WaitForSingleObjectEx(self->_shutdownEvent, INFINITE, TRUE) == WAIT_IO_COMPLETION) 
    { 
        // loop waiting for APC, any other return should exit the thread 
    } 
} 
  
// Init thread and async queue 
HRESULT Sample::_InitQueueThread() 
{ 
    HRESULT hr = S_OK; 
    _shutdownEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); 
    if (_shutdownEvent == nullptr) 
    { 
        hr = HRESULT_FROM_WIN32(GetLastError()); 
    } 
     
    if (SUCCEEDED(hr)) 
    { 
        _completeThread = CreateThread(nullptr, 0, _CompleteThreadProc, this, 0, &_completeThreadId); 
        if (_completeThread == nullptr) 
        { 
            hr = HRESULT_FROM_WIN32(GetLastError()); 
        } 
    } 
    if (SUCCEEDED(hr)) 
    { 
        hr = XTaskQueueCreate(XTaskQueueDispatchMode::ThreadPool, XTaskQueueDispatchMode::Manual, &_asyncCompleteQueue); 
    } 
    return hr; 
} 
  
void Sample::_CancelReadContainerBlobsAsync() 
{ 
    if (_asyncLoad) 
    { 
        XAsyncCancel(_asyncLoad); 
    } 
}
```

## 요구 사항

**헤더:** XGameSave.h

**라이브러리:** xgameruntime.lib

**지원되는 플랫폼:** Windows, XBOX One 계열 콘솔 및 XBOX Series 콘솔

## 함께 보기

[XGameSave](/reference/system/xgamesave/xgamesave_members)\
[XGameSaveBlobInfo](/reference/system/xgamesave/structs/xgamesaveblobinfo)\
[XGameSaveReadBlobDataResult](/reference/system/xgamesave/functions/xgamesavereadblobdataresult)\
[XGameSaveReadBlobData](/reference/system/xgamesave/functions/xgamesavereadblobdata)\
[게임 저장 디버깅](/build/core-features/common/game-save/game-saves-debugging)


## Related topics

- [XGameSaveReadBlobData](/ko/reference/system/xgamesave/functions/xgamesavereadblobdata.md)
- [XGameSaveReadBlobDataResult](/ko/reference/system/xgamesave/functions/xgamesavereadblobdataresult.md)
- [XGameSaveBlob](/ko/reference/system/xgamesave/structs/xgamesaveblob.md)
- [XGameSave](/ko/reference/system/xgamesave/xgamesave_members.md)
- [GDK용 Unity C# API 래퍼](/ko/build/gdk-and-engines/unity/unity-api-wrappers.md)
