7

StreamReaderを使用してWebサーバーと通信するクライアント側のメソッドgetRecordsからReadToEndメソッドを呼び出しているときに、オブジェクトが破棄された例外が発生します。

getRecordsへの最初の呼び出しは成功し、その後の呼び出し中にのみ例外が発生するため、StreamReaderと関連するWebRequestを適切に閉じて破棄していません。

これらの2つのオブジェクトをusingステートメントでラップできることは承知していますが、それはtry / catch/finallyステートメントに展開されるだけです。以下のコードでわかるように、finally句でクリーンアップしています。

したがって、私はusingステートメントが行うことを行っていないか、finallyステートメントに欠けている可能性のある他の何かがあります。私は自分のコードが明示的であることが好きなので、可能な限りusingステートメントを使用したくありません。

コードと関連する例外は次のとおりです。

    public int getRecords(string[] args, string[] vals)
    {
        List<string> urlList = BuildUrlRequestStrings(args, vals); 

        WebRequest request = null;
        WebResponse wresponse = null;
        StreamReader sr = null;           

        foreach (string url in urlList)
        {   
            request = WebRequest.Create(url);

            request.Method = "GET";
            request.ContentType = "application/json";
            //request.Timeout = -1;
            request.Timeout = 300000;
            request.Credentials = CredentialCache.DefaultCredentials;
            //request.ContentType = "application/xml";

            try
            {
                wresponse = request.GetResponse();

                /*using (StreamReader sr = new StreamReader(wresponse.GetResponseStream()))
                {
                    _recieveBuffer = sr.ReadToEnd().ToString();
                }*/
                sr = new StreamReader(wresponse.GetResponseStream());
                _recieveBuffer = sr.ReadToEnd();

                //List<T> temp = JsonConvert.DeserializeObject<List<T>>(_recieveBuffer);
                List<T> temp = JsonConvert.DeserializeObject<List<T>>(
                    _recieveBuffer,
                    new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }
                );

                _recieveData.AddRange(temp);                    
            }
            catch (WebException ex)
            {
                if (ex.Response != null)
                {
                    // can use ex.Response.Status, .StatusDescription         
                    if (ex.Response.ContentLength != 0)
                    {
                        using (var stream = ex.Response.GetResponseStream())
                        {
                            using (var reader = new StreamReader(stream))
                            {
                                Log.Info(FIDB.TAG1, "   WSBuffer.getRecords: WEBSERVER MESSAGE: " + reader.ReadToEnd());
                            }
                        }
                    }
                }

                return -1;
            }
            finally
            {
                if (sr != null)
                {
                    sr.Close();
                    sr.Dispose();
                }

                if (wresponse != null)
                {
                    wresponse.Close();
                    wresponse.Dispose();
                }
            }
        }

        return _recieveData.Count;
    }

07-02 11:32:15.076:I / <<< FI >>>(2775):StorageRelayService.RequestQueueThread:EXCEPTION:System.ObjectDisposedException:オブジェクトは破棄された後に使用されました。07-02 11:32:15.076:I / <<< FI >>>(2775):System.Net.WebConnection.BeginRead(System.Net.HttpWebRequestリクエスト、System.Byte []バッファー、Int32オフセット、Int32サイズ、System.AsyncCallback cb、System.Object state)[0x00000] in:0 07-02 11:32:15.076:I / <<< FI >>>(2775):at System.Net.WebConnectionStream.BeginRead(System。 Byte []バッファー、Int32オフセット、Int32サイズ、System.AsyncCallback cb、System.Object状態)[0x00000] in:0 07-02 11:32:15.076:I / <<< FI

(2775):System.Net.WebConnectionStream.Read(System.Byte []バッファー、Int32オフセット、Int32サイズ)[0x00000] in:0 07-02 11:32:15.076:I / <<< FI >>> (2775):at System.IO.StreamReader.ReadBuffer()[0x00000] in:0 07-02 11:32:15.076:I / <<< FI >>>(2775):at System.IO.StreamReader.Read (System.Char []バッファー、Int32インデックス、Int32カウント)[0x00000] in:0 07-02 11:32:15.076:I / <<< FI(2775):at System.IO.StreamReader.ReadToEnd()[ 0x00000] in:0 07-02 11:32:15.076:I / <<< FI >>>(2775):at FieldInspection.Shared.Buffer.WSBuffer1[FieldInspection.Shared.Model.AggregateRoot.Parcel].getRecords (System.String[] args, System.String[] vals) [0x00000] in <filename unknown>:0 07-02 11:32:15.076: I/<<< FI >>>(2775): at FieldInspection.Shared.Repository.REST.RepositoryREST1 [FieldInspection.Shared.Model.AggregateRoot.Parcel] .Read(IConditions condition)[0x00000] in:0 07-02 11:32:15.076:I / <<< FI >>>(2775):at FieldInspection.Shared .Model.DataAccess.ParcelRepositoryREST.parcelByIdList(System.Collections.Generic.List 1 parcelIdList, Boolean bCurrent, Boolean bHistorical) [0x00000] in <filename unknown>:0 07-02 11:32:15.076: I/<<< FI >>>(2775): at FieldInspection.Droid.StorageRelayService.ProcessRequestGetParcelCache (FieldInspection.Shared.Database.IPC.Request request) [0x00000] in <filename unknown>:0 07-02 11:32:15.076: I/<<< FI >>>(2775): at FieldInspection.Droid.StorageRelayService.ProcessRequestFromForegroundActivity (System.Collections.Generic.List1 reqList)[0x00000] in:0 07-02 11:32:15.076:I / <<< FI >>>(2775):FieldInspectionで。 Droid.StorageRelayService.RequestQueueThread()[0x00000] in:0

4

4 に答える 4

2

「using」ステートメントを使用することを強くお勧めします。WebResponseとStreamReaderが適切に配置されていることがわかると、デバッグが容易になります。

また、ループの反復ごとにWebRequestオブジェクトを作成します。恥ずかしがり屋のアプローチを試してみませんか?

この投稿は役立つかもしれません:HttpWebRequest(.NET)を非同期的に使用する方法は?

于 2012-12-24T17:02:55.700 に答える
1

あなたはすでに答えを受け入れていることを私は知っていますが、別の解決策は変数宣言をループに置くことです。foreach

foreach (string url in urlList)
{ 
    WebRequest request = null;
    WebResponse wresponse = null;
    StreamReader sr = null;  
    ...
}

次に、各ループは独自のインスタンスを取得し、.Dispose()期待どおりに機能します。

于 2012-12-24T17:27:46.110 に答える
0

最初の実行に問題がなく、次の実行で問題が発生する場合は、ガベージコレクターが閉じたオブジェクトをクリーンアップしなかったことが原因である可能性があります。finallyブロックの最後で次のようにします。

GC.Collect();
GC.WaitForPendingFinalizers();
于 2012-12-25T07:42:23.350 に答える
-2

usingスコープを失うと接続が閉じられるので、これを利用してください。

于 2012-12-24T16:54:34.150 に答える