2

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

该代码尝试不断地进行 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。

以下是我的代码:

参考.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 (这就是我重现此异常的方式)。

任何有关这方面的帮助将不胜感激,因为我这几天一直在尝试解决这个问题。

谢谢森希尔

4

1 回答 1

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);
        }
    }
    
于 2017-01-25T07:10:35.573 回答