如何使用TIdHTTP

时间:2019-01-28 18:08:38

标签: multithreading c++builder indy idhttp

我目前正在将Indy的TIdHTTP与我的Embarcadero C ++ Builder 10.1 Berlin一起使用。我已经阅读了一些有关如何使TIdHTTP多线程的在线教程,但是主要问题是我已经在线程中测试了此组件。

这就是它的工作方式。我创建了一个线程对象,并创建了一个函数来下载该线程中的文件,显然该线程可以正常工作,并且文件已下载到我的磁盘中。但是,当我创建其他文件下载线程时,第一个线程停止。我不希望那样,我希望两个文件都可以继续同时下载(而不暂停第一个线程),就像在IDM(Internet下载管理器)中一样。

线程类类似于下面的代码:

class TIdHTTPThread : public TThread
{
protected:
        void __fastcall Execute();
        void __fastcall PutDownloadedFile();
    public:
        __fastcall TIdHTTPThread(bool CreateSuspended);
        void __fastcall IdHTTPBeginWork(TObject *ASender, TWorkMode AWorkMode,
              __int64 AWorkCountMax);
        void __fastcall IdHTTPWork(TObject *ASender, TWorkMode AWorkMode,
          __int64 AWorkCount);
        void __fastcall IdHTTPEndWork(TObject *ASender, TWorkMode AWorkMode);
        void __fastcall DownloadFile(UnicodeString AFileURL, UnicodeString AFileDest);
        void __fastcall CreateQueue(TWinControl* wcParent, TAlign alAlign);
    private:
        TIdHTTP* IdHTTP;
        TMemoryStream* msMemoryStream;
        UnicodeString uFileURL;
        UnicodeString uFileDest;
        int iDownProgress;
        int iFileSize;
        int iMaxProgress;
        int iDownSpeed;
        TWinControl* wcParent;
        TIFDQueue *ifdQueue;
};

请不要为该类中的其他属性和方法而烦恼,我只是想实现我所需要的内容。

CPP文件:

void __fastcall TIdHTTPThread::CreateQueue(TWinControl* wcParent, TAlign alAlign)
{
    this->wcParent = wcParent;
    ifdQueue = new TIFDQueue(this->wcParent, alAlign);
}

void __fastcall TIdHTTPThread::IdHTTPBeginWork(TObject *ASender, TWorkMode AWorkMode,
              __int64 AWorkCountMax)
{
    this->iFileSize     = AWorkCountMax;
    this->iMaxProgress  = AWorkCountMax;
    ifdQueue->SetFileSize(this->iFileSize);
    ifdQueue->SetMaxProgress(this->iMaxProgress);
    ifdQueue->SetFileURL(this->uFileURL);
    ifdQueue->SetFilePath(this->uFileDest);
    ifdQueue->OnBeginUpdate();
}

void __fastcall TIdHTTPThread::IdHTTPWork(TObject *ASender, TWorkMode AWorkMode,
          __int64 AWorkCount)
{
    this->iDownProgress = AWorkCount;
    this->iDownSpeed    = AWorkCount / 1024;
    ifdQueue->SetDownProgress(this->iDownProgress);
    ifdQueue->SetDownSpeed(this->iDownSpeed);
    ifdQueue->OnWorkUpdate();
}

void __fastcall TIdHTTPThread::IdHTTPEndWork(TObject *ASender, TWorkMode AWorkMode)
{
    ifdQueue->OnEndUpdate();
    this->Terminate();
}
//**//

void __fastcall TIdHTTPThread::DownloadFile(UnicodeString AFileURL, UnicodeString AFileDest)
{
    this->uFileURL  = AFileURL;
    this->uFileDest = AFileDest;
}

void __fastcall TIdHTTPThread::PutDownloadedFile()
{
    try {
        this->msMemoryStream = new TMemoryStream;
        this->IdHTTP                = new TIdHTTP(NULL);
        this->IdHTTP->OnWorkBegin   = this->IdHTTPBeginWork;
        this->IdHTTP->OnWork        = this->IdHTTPWork;
        this->IdHTTP->OnWorkEnd     = this->IdHTTPEndWork;
        this->IdHTTP->ConnectTimeout = 20000;
        this->IdHTTP->ReadTimeout   = 60000;
        this->IdHTTP->Get(this->uFileURL, this->msMemoryStream);
        this->msMemoryStream->SaveToFile(this->uFileDest);
    } __finally {
        delete this->msMemoryStream;
        delete this->IdHTTP;
    }
}

__fastcall TIdHTTPThread::TIdHTTPThread(bool CreateSuspended)
    : TThread(CreateSuspended)
{

}
//---------------------------------------------------------------------------
void __fastcall TIdHTTPThread::Execute()
{
    //---- Place thread code here ----
    FreeOnTerminate = true;
    Synchronize(&this->PutDownloadedFile);
}
//---------------------------------------------------------------------------

更新:

void __fastcall TIdHTTPThread::PutDownloadedFile()
{
    try {
        this->CookieManager = new TIdCookieManager(NULL);
        this->SSLIOHandlerSocket = new TIdSSLIOHandlerSocketOpenSSL(NULL);
        this->msMemoryStream = new TMemoryStream;
        // Configure SSL IOHandler
        this->SSLIOHandlerSocket->SSLOptions->Method = sslvSSLv23;
        this->SSLIOHandlerSocket->SSLOptions->SSLVersions = TIdSSLVersions() << sslvTLSv1_2 << sslvTLSv1_1 << sslvTLSv1;
        // Setup HTTP
        this->IdHTTP                  = new TIdHTTP(NULL);
        this->ifdQueue->StopDownload(this->IdHTTP);  // Function To stop download When Fired (doesn't fire imidiatly)
        this->IdHTTP->OnWorkBegin     = this->IdHTTPBeginWork;
        this->IdHTTP->OnWork          = this->IdHTTPWork;
        this->IdHTTP->OnWorkEnd       = this->IdHTTPEndWork;
        this->IdHTTP->OnRedirect      = this->IdHTTPRedirect;
        this->IdHTTP->HandleRedirects = true;
        this->IdHTTP->AllowCookies    = true;
        this->IdHTTP->CookieManager   = this->CookieManager;
        this->IdHTTP->IOHandler       = this->SSLIOHandlerSocket;
        this->IdHTTP->Get(this->uFileURL, this->msMemoryStream);
        if ( this->msMemoryStream->Size >= this->IdHTTP->Response->ContentLength ) {
            this->msMemoryStream->SaveToFile(this->uFileName);
        }
    } __finally {
        delete this->msMemoryStream;
        delete this->CookieManager;
        delete this->SSLIOHandlerSocket;
        delete this->IdHTTP;
    }
}

1 个答案:

答案 0 :(得分:1)

问题在于您线程的//... function mapDispatchToProps(dispatch) { return { fetchAdminSettings(organization) { dispatch({ type: FETCH_ADMIN_SETTINGS }); firebase.database().ref(`${organization}/admin`) .on('value', snapshot => { dispatch({ type: FETCH_ADMIN_SETTINGS_SUCCESS, payload: snapshot.val() }); }); }, logout() { // ... } } } export default connect(mapStateToProps, mapDispatchToProps)(SettingsScreen); 方法正在WebElement web_element_found = driver.findElement(By.id("ctl00_ctl00_cphBMain_cphMain_lblObjects")); String element_text = web_element_found.getText(); 调用中完成所有工作,因此实际上所有线程的工作都在主UI线程中完成,从而序列化了下载和打破了使用工作线程的全部观点。

请勿使用Execute()本身调用Synchronize()。在更新UI控件时,您需要改为更改单个PutDownloadedFile()状态事件,以使用Synchronize()(或TIdHTTP)。