2011-01-28 9 views
3

次のコードでは、client.Connect.Receiveが "byte [] result"を永続的に固定しているため、メモリが解放されることはありません(常に固定されているため)。私は、C#に、this.OnReceiveで使用された後に結果が固定される必要がないことをC#に伝える方法を探していますが、これを行うための組み込み関数またはキーワードは見つかりません。C#でバイト[]を手動で固定解除しますか?

誰かがC#でbyte []配列を固定解除する方法を知っていますか?

//Pin it 
GCHandle myArrayHandle = GCHandle.Alloc(result,GCHandleType.Pinned); 
//use array 
while (r < length) 
{ 
    int bytes = client.Client.Receive(result, r, length - r, SocketFlags.None); 
    r += bytes; 
} 
//Unpin it 
myArrayHandle.Free(); 

しかし、私は個人的にクライアントそのかなり驚かれることと思います:thusly、それを自分の固定を解除/

this.m_TcpListener = new TcpListener(this.p_TcpEndPoint.Port); 
this.m_TcpThread = new Thread(delegate() 
{ 
    try 
    { 
     this.m_TcpListener.Start(); 
     while (this.p_Running) 
     { 
      TcpClient client = this.m_TcpListener.AcceptTcpClient(); 
      new Thread(() => 
       { 
        try 
        { 
         // Read the length header. 
         byte[] lenbytes = new byte[4]; 
         int lbytesread = client.Client.Receive(lenbytes, 0, 4, SocketFlags.None); 
         if (lbytesread != 4) return; // drop this packet :(
         int length = System.BitConverter.ToInt32(lenbytes, 0); 
         int r = 0; 

         // Read the actual data. 
         byte[] result = new byte[length]; 
         while (r < length) 
         { 
          int bytes = client.Client.Receive(result, r, length - r, SocketFlags.None); 
          r += bytes; 
         } 

         Console.WriteLine("Received TCP packet from " + (client.Client.RemoteEndPoint as IPEndPoint).Address.ToString() + "."); 
         this.OnReceive(client.Client.RemoteEndPoint as IPEndPoint, result, length); 
        } 
        catch (SocketException) 
        { 
         // Do nothing. 
        } 

        client.Close();         
       }).Start(); 
      //this.Log(LogType.DEBUG, "Received a message from " + from.ToString()); 
     } 
    } 
    catch (Exception e) 
    { 
     if (e is ThreadAbortException) 
      return; 
     Console.WriteLine(e.ToString()); 
     throw e; 
    } 
} 
); 
this.m_TcpThread.IsBackground = true; 
this.m_TcpThread.Start(); 
+12

**決して**スローeを書いてください。代わりに 'throw;'と書いてください。それ以外の場合は、スタックトレースを破棄します。 – SLaks

+0

「それは思われます」と言うと、どうやってこれを知っていますか?どのような証拠が、メモリが固定されていると仮定するように導くのでしょうか? – Gabe

+0

フレームワークコードにはこのような既知のリークはありません。バッファは* fixed *キーワードで固定されます。あなたはThread.Abort()でいくつかの危険なゲームをしているようですが、私はそこを見るでしょう。 –

答えて

5

あなたがピンすることができます(これは私のC#アプリケーションでのメモリリークの発生源の一つです)。 Connect.Receiveはそれを常に「ピン」に固定します。私はこれを以前に使ったことがあります(確かに多くの人が持っていると思いますが)。代わりに、問題があると確信している場合は、新しい結果配列を毎回割り当てる代わりに、whileループ全体で1つずつ再利用することができます(リスナーを開始する場所に割り当て、毎回lenbytesバイトのみを使用します)。

+0

これは私が持っていた問題を解決しませんでしたが、それはオブジェクトの手動解凍の問題に答えるように見えるので、私はそれを正しい理由としてマークしました。 –

+0

@GWLlosa素晴らしい投稿をいただき、ありがとうございます。これは、手作業による解凍を扱う唯一の場所です。私はbyte []が固定されている状況があり、固定解除したいと思っています。唯一の問題は、私はそれらを固定する人ではないため、私は素晴らしいmyArrayHandleを呼び出すことができません.Free()を呼び出します。私のバッファは、同期ネットワークを実行している最中にランタイムによって舞台裏で固定されています。手動で固定するとバックグラウンドの固定が上書きされるため、手動で固定解除できますか? – kmarks2

+0

?もちろん、これはオブジェクトの固定を解除しません。最後のピン止めハンドルが破棄されたときにのみ、ピン止めが取り除かれます。 – usr

関連する問題