2

我想解決我的一個智能設備項目(Windows Mobile 6.5設備上的.NET CF 3.5)的問題。.NET CF WebService ObjectDisposedException

該代碼試圖不斷調用web服務調用來獲取一些數據並在窗體中使用它。在使用過程中,對於特定情況,會拋出ObjectDisposedException並導致應用程序崩潰。堆棧跟蹤是

System.ObjectDisposedException was unhandled 
Message="ObjectDisposedException" 
ObjectName="" 
StackTrace: 
     at System.Threading.Timer.throwIfDisposed() 
     at System.Threading.Timer.Change(UInt32 dueTime, UInt32 period) 
     at System.Threading.Timer.Change(Int32 dueTime, Int32 period) 
     at System.Net.HttpWebRequest.startReadWriteTimer() 
     at System.Net.HttpWebRequest.ConnectionClient.Read(Byte[] data, Int32 offset, Int32 length) 
     at System.Net.HttpReadStream.NetworkRead(Byte[] data, Int32 offset, Int32 length) 
     at System.Net.ChunkedReadStream.fillBuffer() 
     at System.Net.ChunkedReadStream.getLine() 
     at System.Net.ChunkedReadStream.doRead(Byte[] data, Int32 offset, Int32 length) 
     at System.Net.HttpReadStream.ReadToDrain(Byte[] buffer, Int32 offset, Int32 length) 
     at System.Net.HttpReadStream.doClose() 
     at System.Net.HttpReadStream.Finalize() 

我看了很多博客和論壇,包括這一點,並提出解決方案似乎是關閉的請求流和要求,得到響應之前。

requestStream = webRequest.GetRequestStream(); 
requestStream.Close(); // WE NEED THIS LINE in order to avoid the ObjectDisposedException. 

但這並不能幫助我的情況。如果requestStream在寫入數據流之前關閉,那麼它不會執行任何操作。如果我在得到響應後關閉,則會拋出InvalidOperationException。

以下是我的代碼:

Reference.cs

[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
[System.Web.Services.WebServiceBindingAttribute(Name="ProductResolveServiceSOAP11Binding", Namespace="urn:ProductResolveService")] 
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Exception))] 
public partial class ProductResolveService : System.Web.Services.Protocols.SoapHttpClientProtocol { 

    /// <remarks/> 
    public ProductResolveService() { 
     this.Url = "http://172.26.37.115:8080/axis/services/ProductResolveService"; 
    } 

    /// <remarks/> 
    [System.Web.Services.Protocols.SoapDocumentMethodAttribute("urn:getResolvedEpcs", RequestNamespace="http://services.axis.oatsystems.com", ResponseNamespace="http://services.axis.oatsystems.com", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] 
    [return: System.Xml.Serialization.XmlElementAttribute("return", IsNullable=true)] 
    public ResolvedProductList getResolvedEpcs([System.Xml.Serialization.XmlElementAttribute(IsNullable=true)] EpcToResolve message) { 
     object[] results = this.Invoke("getResolvedEpcs", new object[] { 
        message}); 
     return ((ResolvedProductList)(results[0])); 
    } 

    /// <remarks/> 
    public System.IAsyncResult BegingetResolvedEpcs(EpcToResolve message, System.AsyncCallback callback, object asyncState) { 
     return this.BeginInvoke("getResolvedEpcs", new object[] { 
        message}, callback, asyncState); 
    } 

    /// <remarks/> 
    public ResolvedProductList EndgetResolvedEpcs(System.IAsyncResult asyncResult) { 
     object[] results = this.EndInvoke(asyncResult); 
     return ((ResolvedProductList)(results[0])); 
    } 
} 

Form1.cs的

using System; 
using System.Collections.Generic; 
using System.Net; 
using System.Threading; 
using System.Web.Services.Protocols; 
using System.Windows.Forms; 
using NFEHandlingProject.StatusService; 
using System.IO; 
using MVProductResolveService; 


namespace NFEHandlingProject 
{ 
    public partial class Form1 : Form 
    { 
     private Thread resolveThread; 
     int counter = 0; 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void btnStart_Click(object sender, EventArgs e) 
     { 
      if (resolveThread == null) 
      { 
       this.BeginInvoke((Action)delegate { lstbxStatusMsgs.Items.Add("Resolve Product: Creating Thread"); lstbxStatusMsgs.SelectedIndex = lstbxStatusMsgs.Items.Count - 1; }); 

       resolveThread = new Thread(new ThreadStart(GetEpcProductMapping)); 
       resolveThread.IsBackground = true; 
       resolveThread.Priority = ThreadPriority.BelowNormal; 

       resolveThread.Start(); 
      } 
     } 

     object syncRoot2 = new object(); 
     bool resolving = false; 

     private void GetEpcProductMapping() 
     { 
      lock (syncRoot2) 
      { 
       if (resolving) 
       { 
        return; 
       } 

       resolving = true; 
      } 

      while (resolving) 
      { 
       using (ProductResolveService2 productResolveService = new ProductResolveService2()) 
       { 
        EpcToResolve epcToResolve = null; 

        try 
        { 
         this.BeginInvoke((Action)delegate { lstbxStatusMsgs.Items.Add("Resolve Product: Resolving..."); lstbxStatusMsgs.SelectedIndex = lstbxStatusMsgs.Items.Count - 1; }); 

         productResolveService.Url = "http://172.26.37.115:8080/axis/services/ProductResolveService?wsdl"; 

         productResolveService.Timeout = 60000; 

         // The input object that is sent to xpress 
         epcToResolve = new EpcToResolve(); 

         string epcBase = "3410402AEA0000000000"; 
         int baseDec = Convert.ToInt32("1000", 16); 

         // Creating the input of epc's baed on the ResolveBatchSize and number epcs's that needs to be resolved at xpress 
         string[] epcs = new string[1]; 
         for (int i = 0; i < 1; i++) 
         { 
          int epcDec = baseDec + i; 
          epcs[i] = epcBase + epcDec.ToString("X"); 
         } 

         // setting the epc list which is the input that is sent to xpress 
         epcToResolve.epcList = epcs; 

         //pass the flag to check if say whether the productInformation or just the product_id is resolved 
         epcToResolve.returnOnlyProductId = false; 

         //return productResolveService.getResolvedEpcs(epcToResolve); 
         productResolveService.getResolvedEpcs(epcToResolve); 
         this.BeginInvoke((Action)delegate { lstbxStatusMsgs.Items.Add("Resolved"); lstbxStatusMsgs.SelectedIndex = lstbxStatusMsgs.Items.Count - 1; }); 
        } 
        catch (SoapHeaderException) 
        { 
         // do nothing 
        } 
        catch (SoapException se) 
        { 
         this.BeginInvoke((Action)delegate { lstbxStatusMsgs.Items.Add("Problem resolving products at xpress"); lstbxStatusMsgs.SelectedIndex = lstbxStatusMsgs.Items.Count - 1; }); 
        } 
        catch (WebException we) 
        { 
         // get the reason for the exception 
         WebExceptionStatus status = we.Status; 
         String description = we.Message; 

         WebResponse response = we.Response; 
         if (response != null) 
         { 
          Stream respStream = response.GetResponseStream(); 

          if (respStream != null) 
          { 
           respStream.Close(); 
           respStream.Dispose(); 
           respStream = null; 
          } 
          // close the response 
          response.Close(); 
          response = null; 
         } 
         // Case when there is no connectivity. Just display an error message to the user to indicate that there is no connectivity. 
         this.BeginInvoke((Action)delegate { lstbxStatusMsgs.Items.Add("Resolve Product: There is no connectivity to xpress"); lstbxStatusMsgs.SelectedIndex = lstbxStatusMsgs.Items.Count - 1; }); 
        } 
        catch (ThreadAbortException) 
        { 
         // Do nothing. Do not log 
        } 
        catch (System.Exception e) 
        { 
         this.BeginInvoke((Action)delegate { lstbxStatusMsgs.Items.Add("An exception occured when fetching data from xpress"); lstbxStatusMsgs.SelectedIndex = lstbxStatusMsgs.Items.Count - 1; }); 
        } 

        try 
        { 
         Thread.Sleep(200); 
        } 
        catch 
        { 
        } 
       } 
      } 

      resolving = false; 
     } 

     private void btnStop_Click(object sender, EventArgs e) 
     { 
      if (resolveThread != null && resolving) 
      { 
       resolveThread.Abort(); 
       resolveThread.Join(); 
       resolveThread = null; 
       resolving = false; 

       this.BeginInvoke((Action)delegate { lstbxStatusMsgs.Items.Add("Resolve Product: Stopped Thread"); lstbxStatusMsgs.SelectedIndex = lstbxStatusMsgs.Items.Count - 1; }); 
      } 
     } 
    } 
} 

在點擊開始按鈕的形式,在創建線程,並保持通話web服務,當停止被調用時,線程停止。重複的啓動和停止會導致ObjectDisposedException(這是我重現此異常的方式)。

任何有關這方面的幫助將高度讚賞,因爲我幾天來一直在試圖解決這個問題。

感謝 塞特希

+0

你有沒有確定究竟在何處的錯誤是從你的代碼來嗎?它是否來自getResolvedEpcs的調用,因爲消息在被訪問之前被丟棄?有沒有更多的堆棧跟蹤,或者有錯誤的內部異常? – Nanhydrin

+0

這是從.NET代碼,而不是從我的代碼。到目前爲止,我的解釋是我不應該重用存根(ProductResolveService),我需要每次關閉請求流和響應流。如果沒有這樣做,那麼會有一個Timer(用於異步調用)喚醒並試圖訪問請求/響應流(我不知道哪一個),並發現它已經處理,因此會拋出此異常。我所做的調用是同步的,我不知道爲什麼Timer仍在使用中。 – Senthil

+0

錯誤只發生在您停止或僅僅是隨機發生之後? – Nanhydrin

回答

1

這是一個很老的帖子。然而,我想在這裏記錄我的答案,任何仍在尋找答案的機構。

兩個選項:

  1. 移動到WCF客戶是更容易和更清潔。
  2. 使用下面的解決方案。

    public class ExtendedDataImport : DataImport.DataImport 
    { 
        private WebRequest webRequest; 
        private WebResponse webResponse; 
    
        /// <summary> 
        /// This method overrides the generated method and sets parameters so that HTTP 1.0 
        /// is used (without chunking). If left with default parameters it 
        /// sometimes fails. 
        /// </summary> 
        protected override WebRequest GetWebRequest(Uri uri) 
        { 
         webRequest = base.GetWebRequest(uri); 
         ((HttpWebRequest)webRequest).KeepAlive = false; 
         ((HttpWebRequest)webRequest).ProtocolVersion = HttpVersion.Version10; 
         return webRequest; 
        } 
    
        protected override WebResponse GetWebResponse(WebRequest request) 
        { 
         webResponse = base.GetWebResponse(request); 
         return webResponse; 
        } 
    
        public void Close() 
        { 
         if (webResponse != null) 
         { 
          Stream responseStream = webResponse.GetResponseStream(); 
          responseStream.Close(); 
          responseStream.Dispose(); 
          responseStream = null; 
          webResponse.Close(); 
          webResponse = null; 
         } 
    
         if (webRequest != null) 
         { 
          // Aborting the WebRequest, cleans up the webrequest and 
          // stops the timer which causes the ObjectDisposedException 
          try 
          { 
           webRequest.Abort(); 
           webRequest = null; 
          } 
          catch (ObjectDisposedException ex) 
          { 
           // Ignoring the object disposed exception as mentioned in the follwoing link 
           //http://social.msdn.microsoft.com/Forums/en/netfxcompact/thread/8f21514c-9b7c-40d3-96c9-794c0dc167fe 
          } 
         } 
        } 
    
        protected override void Dispose(bool disposing) 
        { 
         Close(); 
         base.Dispose(disposing); 
        } 
    }