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); 
        } 
    }