Инкрементальная загрузка файла с использованием сигналов и слотов

Прежде чем реализовать это, я хотел бы проверить, приведет ли это к неопределенному поведению или условиям гонки.

При загрузке файлов в asure это нужно делать блоками. Я хочу загрузить 5 блоков параллельно, и все они получают свои данные из одного и того же файла. Это произойдет следующим образом:

char *currentDataChunk;
int currentDataChunkSize;

connect(_blobStorageProvider, SIGNAL(putBlockSucceded(int)), this, SLOT(finalizeAndUploadNextBlock(int)));

int parallelUploads = ((_item->size() / MAX_BLOCK_SIZE) >= MAX_PARALLEL_BLOCKUPLOADS) ? MAX_PARALLEL_BLOCKUPLOADS : (_item->size() / MAX_BLOCK_SIZE);

_latestProcessedBlockId = (parallelUploads - 1);

for(int i = 0; i < parallelUploads; i++) {

    currentDataChunkSize = _item->read(currentDataChunk, MAX_BLOCK_SIZE);

    ...

    uploader->putBlock(_container, _blobName, currentDataChunk, i);
}

В функции putBlock в загрузчике он вызывает QNetworkAccessManager с вызовом. Когда это будет сделано, он отправляет обратно сигнал, если он не прошел, успешно или был отменен, вместе с blockId, чтобы я знал, какой из блоков был загружен.

void BigBlobUploader::finalizeAndUploadNextBlock(int blockId) {

    // FINALIZE BY ADDING SUCCESSFUL BLOCK TO FUTURE BLOCKLIST
    QByteArray temp;

    for(int i = 0; i != sizeof(blockId); i++) {
        temp.append((char)(blockId >> (i * 8)));
    }

    _uploadedBlockIds.insert(blockId, QString(temp.toBase64()));
    this->uploadNextBlock();
} 

void BigBlobUploader::uploadNextBlock() {

    char *newDataChunk;
    int newDataChunkSize = _item->read(newDataChunk, MAX_BLOCK_SIZE);
    ...
    _latestProcessedBlockId++;
    uploader->putBlock(_container, _blobName, newDataChunk, _latestProcessedBlockId);
}

Мой план сейчас состоит в том, чтобы получить эти сигналы в слот, который должен принять к сведению, что этот блок был загружен (поместите его в список, чтобы иметь возможность поместить список блоков для завершения этого блоба), увеличить индекс на единицу (который начинается с 5 ), получить новый фрагмент данных и повторить весь процесс.

Моя проблема сейчас в том, что, если два из них закончатся в ТОЧНОЕ время? Я не имею здесь дело с потоками, но поскольку HTTP-запросы по умолчанию разделены на потоки, в чем здесь дело? Сигналы поставлены в очередь (или мне следует использовать QueuedConnection)? Можно ли вызывать слот параллельно? Есть ли лучший способ сделать это?


person chikuba    schedule 19.04.2012    source источник


Ответы (2)


Извините за неудобства, я предположил, что вы используете .NET, так как вы добавили тег Windows Azure в эту тему. Я знаком с Windows Azure, но мое понимание Qt ограничено. Однако это не будет отличаться от использования сигналов/слотов в других параллельных сценариях. Этот документ может помочь: http://qt-project.org/doc/qt-4.8/signalsandslots.html.

С уважением,

Мин Сюй.

person Ming Xu - MSFT    schedule 19.04.2012

Я не знаком с QNetworkAccessManager. Но в целом, чтобы справиться с условиями гонки, используйте блокировки. Обычно способ использования блокировок в C# заключается в использовании ключевого слова lock. Что-то типа:

private object lockingObject = new object();

In a method:

lock
{
                // If a thread acquires a lock, another thread is blocked here until the lock is released.
}

Кроме того, вы можете обратиться к http://msdn.microsoft.com/en-us/library/c5kehkcz(v=vs.100).aspx для получения дополнительной информации.

С уважением,

Мин Сюй.

person Ming Xu - MSFT    schedule 19.04.2012
comment
дело в том, что у меня не будет разных потоков, обращающихся к этому слоту, и мне нужно знать, как это будет работать с механизмом сигнала/слота в qt/c++, а не в c# - person chikuba; 19.04.2012