在实施此之前,我想检查这是否会导致未定义的行为或竞争条件。
确保上传文件时,必须分块完成。我想并行上传 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);
}
我现在的计划是将这些信号提取到一个插槽,该插槽应该注意这个块已上传(将它放在一个列表中以便能够放置一个块列表来完成这个 blob),将索引增加一(从 5 开始) 并获取新的数据块并重做整个过程。
我现在的问题是,如果其中两个同时完成怎么办?我不是在这里处理线程,但是由于默认情况下 HTTP 请求是线程化的,所以这里是什么情况?信号是否排队(或者我应该使用 QueuedConnection)?可以并行调用一个槽吗?有没有更好的方法来做到这一点?