2012-01-26 19 views
1

ファイル転送があり、デバイスがインターネット接続を失ったとき
DataOutputStream.writeは時にはほとんど無限にブロックされます。howto強制的に書き込みブロックを解放する

これは、基本的なソケットレイヤーが可能な限り速くそれを実行しているので、これは正常です。

は私が socket.close()または DataOutputStream.close()
はブロックと通常のコードの流れが速く
を生じる停止する DataOutputStream.writeを強制的にこれが起こるとき

registerReceiver(mConnRec,new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); 

とキャッチを使用して行うことを考えていました。

これは機能しますか、またはブロックを制御するために何ができますか?

は私が持っていた別のIDEには、それは私が多分socket.closeを強制する可能性がfalseを返す場合は、この

public boolean haveNetworkConn(Context ctx) 
{ 
    boolean HaveConnectedWifi = false; 
    boolean HaveConnectedMobile = false; 

    ConnectivityManager cm = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE); 
    NetworkInfo[] netInfo = cm.getAllNetworkInfo(); 

    for (NetworkInfo ni : netInfo) 
    { 
     if (ni.getTypeName().equalsIgnoreCase("WIFI")) 
      if (ni.isConnected()) 
       HaveConnectedWifi = true; 
     if (ni.getTypeName().equalsIgnoreCase("MOBILE")) 
      if (ni.isConnected()) 
       HaveConnectedMobile = true; 
    } 
    return HaveConnectedWifi || HaveConnectedMobile; 
} 

のように存在するすべての5秒
テストインターネットへのジョブスレッドを開始しました。

は本当にこのアイデア

UPDATE registerReceiver BroadcastReceiverを使用していくつかのテストを実行する上でいくつかのフィードバックを持っていると思います。
inとOutputStreamとソケット自体を閉じると何も起こりません。 out.write(buffer, 0, val);にブロックされ続けます。これは最も予期しなかったことでした。
Eclipseを使用してブレークポイントを配置し、ステッピング..

private BroadcastReceiver mConnReceiver = new BroadcastReceiver() { 

@Override 
public void onReceive(Context context, Intent intent) { 

    String action = intent.getAction(); 

    if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)){ 
     return; 
    } 

    boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); 
    NetworkInfo aNetworkInfo = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);      

    if (!noConnectivity) 
    { 
     if ((aNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE) || (aNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI)) 
     { 
      //Handle connected case 
     } 
    } 
    else 
    { 
     if ((aNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE) || (aNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI)) 
     { 
      //Handle disconnected case 
      if(socket != null) 
       try { 
        out.close(); 
        in.close(); 
        socket.close(); 

       } catch (IOException e) { 

       } 
     } 
    } 

} 
}; 

答えて

2

はい、ソケットをクローズすると、現在のソケットにブロックされたコールのすべてのメソッドのブロックを解除する方法があります。 the documentation for close()から引用:

現在このソケット時にI/O操作でブロックされた任意のスレッドが のSocketExceptionをスローします。

「Java Concurrency in Practice」のセクション7.1.6も参照してください。

CONNECTIVITY_ACTIONのレシーバを登録すると、CPUサイクルが節約され、アプリケーションの接続変更に対する反応が改善される可能性があるため、5秒ごとにポーリングするよりも優れたソリューションです。

+0

これについていくつかのテストコードを実行します。 – Erik

+0

私の質問が更新されました。テストとブロッキングの実行は放置されません。 DataOutputStream.close()は機能しませんか? SocketはIntentServiceクラスのフィールドであり、ソケットはonHandleIntent()から作業スレッドに渡されます。 – Erik

+0

これは 'socket.shutdownOutput();'を使って動作しています。 – Erik

関連する問題