8

Qt4 を使用してアプリケーションを作成しています。

特定の http アドレスから非常に短いテキスト ファイルをダウンロードする必要があります。

ファイルは短く、アプリを続行できるようにするために必要なので、ダウンロードがブロックされていることを確認したいと思います (または、ファイルが見つからない/利用できない場合は数秒後にタイムアウトします)。

QHttp::get() を使用したかったのですが、これはノンブロッキング メソッドです。

スレッドを使用できると思いました: 私のアプリはそれを開始し、終了するのを待ちます。スレッドはダウンロードを処理し、ファイルのダウンロード時またはタイムアウト後に終了します。

しかし、私はそれを機能させることはできません:

class JSHttpGetterThread : public QThread
{
  Q_OBJECT

public:
  JSHttpGetterThread(QObject* pParent = NULL);
  ~JSHttpGetterThread();

  virtual void run()
  {
    m_pHttp = new QHttp(this);
    connect(m_pHttp, SIGNAL(requestFinished(int, bool)), this, SLOT(onRequestFinished(int, bool)));

    m_pHttp->setHost("127.0.0.1");
    m_pHttp->get("Foo.txt", &m_GetBuffer);
    exec();
  }

  const QString& getDownloadedFileContent() const
  {
    return m_DownloadedFileContent;
  }

private:
  QHttp* m_pHttp;

  QBuffer m_GetBuffer;
  QString m_DownloadedFileContent;

private slots:
  void onRequestFinished(int Id, bool Error)
  {
    m_DownloadedFileContent = "";
    m_DownloadedFileContent.append(m_GetBuffer.buffer());
  }
};

ダウンロードを開始するスレッドを作成するメソッドでは、次のことを行っています。

JSHttpGetterThread* pGetter = new JSHttpGetterThread(this);
pGetter->start();
pGetter->wait();

しかし、それは機能せず、アプリは待機し続けます。スロット「onRequestFinished」が呼び出されないように見えます。

何か案が ?

私がやろうとしていることを行うためのより良い方法はありますか?

4

6 に答える 6

5

少し遅れますが:これらの待機ループは使用しないでください。正しい方法は、QHttpからのdone()シグナルを使用することです。

私が見たものからのrequestFinishedシグナルは、アプリケーションがリクエストを終了したときのものであり、データはまだダウンしている可能性があります。

新しいスレッドは必要ありません。qhttpを設定するだけです。

httpGetFile= new QHttp();
connect(httpGetFile, SIGNAL(done(bool)), this, SLOT(processHttpGetFile(bool)));

また、ファイルがすべてディスク上にあるとは限らないため、processHttpGetFileでファイルをフラッシュすることを忘れないでください。

于 2008-11-05T15:39:47.283 に答える
4

スレッドを使用する代わりに、次を呼び出すループに入ることができますprocessEvents

while (notFinished) {
   qApp->processEvents(QEventLoop::WaitForMore | QEventLoop::ExcludeUserInput);
}

スロットnotFinishedから設定できるフラグはどこにありますか。onRequestFinished

これExcludeUserInputにより、待機中に GUI 関連のイベントが確実に無視されます。

于 2008-10-31T07:44:03.367 に答える
3

呼び出す必要があるQThread::quit()exit()、完了した場合-そうしないと、スレッドが永久に実行されます...

于 2008-10-30T17:04:21.333 に答える
1

私は、David のソリューションを実装することにしました。

ただし、さらにいくつかのことを処理していました。

  • Qt4.3.3 (私が使用しているバージョン) の QEventLoop 列挙値を調整する必要がありました。
  • 別の要求が終了したときではなく、ダウンロード要求が終了したときに while ループを終了するように、要求 ID を追跡する必要がありました。
  • 問題が発生した場合に while ループを終了できるように、タイムアウトを追加しました。

(多かれ少なかれ)疑似コードとしての結果は次のとおりです。

class BlockingDownloader : public QObject
{
  Q_OBJECT
public:
    BlockingDownloaderBlockingDownloader()
    {
      m_pHttp = new QHttp(this);
      connect(m_pHttp, SIGNAL(requestFinished(int, bool)), this, SLOT(onRequestFinished(int, bool)));
    }

    ~BlockingDownloader()
    {
      delete m_pHttp;
    }

    QString getFileContent()
    {
      m_pHttp->setHost("www.xxx.com");
      m_DownloadId = m_pHttp->get("/myfile.txt", &m_GetBuffer);

      QTimer::singleShot(m_TimeOutTime, this, SLOT(onTimeOut()));
      while (!m_FileIsDownloaded)
      {
        qApp->processEvents(QEventLoop::WaitForMoreEvents | QEventLoop::ExcludeUserInputEvents);
      }
      return m_DownloadedFileContent;
    }

private slots:
    void BlockingDownloader::onRequestFinished(int Id, bool Error)
    {
      if (Id == m_DownloadId)
      {
        m_DownloadedFileContent = "";
        m_DownloadedFileContent.append(m_GetBuffer.buffer());
        m_FileIsDownloaded = true;
      }
    }

  void BlockingDownloader::onTimeOut()
  {
    m_FileIsDownloaded = true;
  }

private:
  QHttp* m_pHttp;
  bool m_FileIsDownloaded;
  QBuffer m_GetBuffer;
  QString m_DownloadedFileContent;
  int m_DownloadId;
};
于 2008-11-03T12:34:51.200 に答える
-1

GUI にスレッドで待機する時間を与えてからあきらめるのはどうですか。

何かのようなもの:

JSHttpGetterThread* pGetter = new JSHttpGetterThread(this);
pGetter->start();
pGetter->wait(10000);  //give the thread 10 seconds to download

または...

GUI スレッドが「ダウンローダー スレッド」を待たなければならないのはなぜですか? アプリが起動したら、ダウンローダー スレッドを作成し、finished() シグナルを他のオブジェクトに接続して、ダウンローダー スレッドを開始し、戻ります。スレッドが終了すると、プロセスを再開できる他のオブジェクトに通知します。

于 2008-10-30T20:24:05.330 に答える