QNetWork AccessManager 비동기식 정보

2762 단어 QT
배경: 최근에 프로젝트 중의 한 문제에 오랫동안 시달렸고 인터넷에서 많은 자료를 찾았지만 해결 방안을 찾지 못했다...나중에 천천히 디버깅을 해서 마침내 알게 되었다. 지금 이 문제를 붙여서 장래에 누군가가 그 중에서 자신이 필요로 하는 답안을 찾을 수 있기를 바란다.
QNetworkAccessManager 소개: QNetworkAccessManager는 네트워크 요청과 선택할 수 있는 데이터를 불러올 수 있는 표준 함수를 제공하고 요청마다 QNetworkReply 대상을 되돌려줍니다.이 되돌아오는 대상은 되돌아오는 요청에 필요한 모든 데이터를 포함하고 있습니다.
일반적인 용도:
  QNetworkAccessManger *manger = new QNetworkAccessManger(this);
  QNetworkReply *reply = manger->get(QNetworkRequest(url));
  connect(reply,SIGNAL(finished()),this,SLOT(finished()));
다운로드가 완료되었을 때finished () 슬롯 함수에서 reply->readAll () 를 통해 다운로드 데이터를 읽을 수 있습니다. 이 과정은 비동기적이며 UI 인터페이스를 막지 않습니다.
다운로드를 동기화하려면 QEventLoop, QEventLoop을 통해 부분적인 이벤트 순환을 설정할 수 있습니다.
  QNetworkAccessManger *manger = new QNetworkAccessManger(this);
  QNetworkReply *reply = manger->get(QNetworkRequest(url));
  QEventLoop loop;
  connect(reply,SLGNAL(finished()),&loop,SLOT(quit()));
  loop.exec();
//다운로드가 완료될 때까지 기다립니다...
문제 설명: 프로젝트에서 하나의 큰 파일을 다른 서버에 나누어 업로드해야 하며, 업로드하기 전에 인코딩을 해야 한다.파일이 10개의 블록으로 분할된다고 가정합니다.
   QNetworkAccessManger *manger = new QNetworkAccessManger(this);
   for(int i=0;i<10;++i)
   { 
      encode(data[i]);//encode는 시간이 많이 걸리기 때문에 약 1s가 필요합니다
      manger->put(QNetworkRequest(url),data[i]);
    }
put은 비동기적이기 때문에 이렇게 쓰면 인코딩과 업로드가 동시에 진행되어야 하는데 사실은 그렇지 않다. 실제 실행 과정은 하나의 데이터 블록을 인코딩한 후에put작업은 이 요청을 대기 대기열에 넣고 10개의 데이터를 모두 인코딩한 후에야 업로드를 시작한다. 즉, 업로드하기 전에 약 10s를 기다려야 한다.Why???
  ……
자료를 검토한 결과 for 순환이 끝나지 않으면 현재 라인의 메시지 순환이 막히고 메시지 대기열 안의 신호를 처리하지 않기 때문에 즉시 업로드할 수 없습니다.
  
해결 방법: 데이터를 다른 루트 (QThread) 에 업로드합니다. 이렇게 업로드하면 이 루트의 메시지 순환에서 처리됩니다.
다음은 프로그램 위조 코드를 직접 보여 줍니다. 기본 독자는 QThread에 대해 알고 더 이상 상세하게 설명하지 않습니다.
//mian.cpp
UploadAssist *uploadAssist = new UploadAssist;
QThread *thread = new QThread;
uploadAssist->moveToThread(thread);
thread->start();
for(int i=0;i<10;++i)
{
    encode(data[i]);
    uploadLAssist->upload(data[i]);
}
//UploadAssist.h
class UploadAssist : public QObject
{
    Q_OBJECT
public:
     UploadAssist();
     void Upload(QByteArray data);
signals:
     void put_signal(QByteArray data);
private slots:
     void put_slot(QByteArray data);
private:
     QNetworkAccessManager *manger;
};
//UploadAssist.cpp
UploadAssist::UploadAssist()
{
    manger = NULL;
    connect(this,SIGNAL(put_signal(QByteArray)),this,SLOT(put_slot(QByteArray)));
}

void UploadAssist::Upload(QByteArray data)
{
    emit put_signal(data);
}
void UploadAssist::put_slot(QByteArray data)
{
    if(manger==NULL)
        manger = new QNetworkAccessManager;
    manger->put(QNetworkRequest(url),data);
}

좋은 웹페이지 즐겨찾기