.NET CF WebService ObjectDisposedException

时间:2012-05-29 07:58:03

标签: compact-framework windows-mobile-6 windows-mobile-6.5 .net-cf-3.5 smart-device

我正在尝试解决我的某个智能设备项目(Windows Mobile 6.5设备上的.NET CF 3.5)的问题。

代码尝试连续进行webservice调用以获取一些数据并在表单中使用它。在使用过程中,对于特定情况,抛出了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服务,当调用stop时,线程将停止。重复启动和停止会导致ObjectDisposedException(这就是我重现此异常的方式)。

对此方面的任何帮助都将受到高度赞赏,因为我一直试图解决这个问题几天。

由于 塞特希

1 个答案:

答案 0 :(得分: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);
        }
    }