7

URLに接続してデータを取得するスレッドがあります。

メソッドhttpConnection.connect();が応答を得るのに時間がかかりすぎることがあり、この接続スレッドの読み込みダイアログを 5 セグに制限したいと考えています。

コードにタイムアウトを追加しようとしましたが、うまくいきません!!

URL formattedUrl = new URL(url); 
            URLConnection connection = formattedUrl.openConnection(); 
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(5000);
            HttpURLConnection httpConnection = (HttpURLConnection) connection;
            httpConnection.setAllowUserInteraction(false);
            httpConnection.setInstanceFollowRedirects(true);
            httpConnection.setRequestMethod("GET");
            httpConnection.setConnectTimeout(5000);
            httpConnection.setReadTimeout(5000);
            httpConnection.connect();

したがって、5000 秒が経過したとき、または使用者が電話の戻るキーを押したときに、connect メソッドとスレッドを停止する必要があります。

これはどのように達成できますか?URL接続スレッドを使用してAndroidでこの作業を行うことに関する情報が見つかりません。

ありがとう

4

3 に答える 3

3

URLConnection のタイムアウト設定は、必要なタイムアウト制御を提供するには不十分です。その理由は次のとおりです。

  • setConnectTimeout() は、サーバーとの接続を確立するだけのタイムアウトを設定します。そのため、タイムアウトは、接続を開くときに、規定の時間内に接続を確立できない場合にのみトリガーされます。

  • setReadTimeount() は、利用可能なデータを読み取るためのタイムアウトを設定します。このため、タイムアウトは、単一の読み取り操作が設定された時間よりも長くブロックされた場合にのみトリガーされます。そのため、接続が遅い場合でも、各読み取り操作がタイムアウトのしきい値に近づくことはありませんが、すべてのデータを読み取るための合計時間は非常に長くなります。

読み取り作業単位全体にタイムアウトを適用する 1 つの解決策は、Java 5 以降に見られる同時実行機能を使用することです。特に、ExecutorServiceFutureを使用すれば十分です。

Runnable task = new Runnable() {
    public void run() {
        // original code to read data from a URL
    }
};

ExecutorService executor = Executors.newSingleThreadExecutor();  // or any other implementation
Future<?> future = executor.submit(task);
try {
    future.get(5, TimeUnit.SECONDS); // wait 5 seconds for task to complete
    // success
} catch (TimeoutException ex) {
    // handle timeout
} finally {
    executor.shutdownNow(); // cleanup
}
于 2012-10-06T01:41:10.950 に答える
3

Brent Worden の答えは正しい方向に進んでいます。しかし、彼の解決策には問題があります。タスクのタイムアウトが発生すると、呼び出したスレッドはfuture.get予想どおり例外を受け取ります。ただし、Runnable.run()メソッドを実行していたワーカー スレッドは、接続または読み取りが完了するのを待ってスタックする場合があります。

これを解決するのは難しいです。私が知る限り、ソケット接続またはソケット ストリームの読み取りまたは書き込みを待機しているスレッドをアンジャムする唯一の信頼できる方法はclose()Socketオブジェクトを呼び出すことです。そして、そのアプローチ (ここ) を使用する際の問題は、標準HttpUrlConnectionオブジェクトがオブジェクトを公開しないSocketことです。

Apache Http クライアント ライブラリを使用することをお勧めします。この質問では、HttpClient を使用する場合にリクエストを中止する方法について説明します: HttpClient リクエストのキャンセル

于 2012-10-06T03:25:30.473 に答える
0

URLConnection.setConnectTimeout(millis)を呼び出すだけで、求めていることを実現できます。指定されたタイムアウトが期限切れになると、SocketTimeoutExceptionがスローされます。

try {
   HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
   con.setConnectTimeout(5000); //set timeout to 5 seconds
} catch (java.net.SocketTimeoutException e) {
   //DO SOMETHING
} catch (java.io.IOException e) {
  //DO SOMETHING
}

注目に値するのは、次のように述べていることです。

このメソッドの一部の非標準実装では、指定されたタイムアウトが無視される場合があります。設定された接続タイムアウトを確認するには、getConnectTimeout() を呼び出してください。

于 2012-10-05T23:42:32.363 に答える