在实施之前,我想检查这是否会导致未定义的行为或竞争条件。
将文件上传到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);
}
我现在的计划是将这些信号提取到一个插槽,应注意该块已上传(将其放入列表中以便能够放置一个块列表来完成此blob),将索引增加一(从5)开始,获取一大块新数据并重做整个过程。
我现在的问题是,如果其中两个完全同时完成怎么办?我不是在这里处理线程,但由于HTTP请求默认是线程化的,这里的情况是什么?信号是否排队(或者我应该使用QueuedConnection)?可以并行调用插槽吗?有没有更好的方法呢?
答案 0 :(得分:0)
很抱歉给您带来不便,我假设您使用的是.NET,因为您已将Windows Azure标记添加到此主题中。我熟悉Windows Azure,但我对Qt的理解有限。但是,它与在其他并发场景中使用信号/插槽没有什么不同。本文档可能有所帮助:http://qt-project.org/doc/qt-4.8/signalsandslots.html。
最诚挚的问候,
徐明。答案 1 :(得分:-1)
我不熟悉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了解更多信息。
最诚挚的问候,
徐明。