2

Я пытаюсь решить проблему с одним из моих проектов Smart Device (.NET CF 3.5 на устройстве Windows Mobile 6.5)..NET CF WebService ObjectDisposedException

Код пытается сделать запросы webservice непрерывно, чтобы получить некоторые данные и использовать их в форме. Во время использования для конкретного случая возникает исключение ObjectDisposedException, и приложение выходит из строя. StackTrace является

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

При нажатии на кнопку Start в форме, поток создается и сохранение вызова webservice, когда вызывается стоп, поток останавливается. Повторное начало и остановка вызывает ObjectDisposedException (таким образом я воспроизвел это исключение).

Любая помощь в этом отношении будет высоко оценена, поскольку я пытался решить эту проблему в течение нескольких дней.

Благодаря Senthil

+0

Вы определили, где именно ошибка исходит из вашего кода? Это от вызова getResolvedEpcs, потому что сообщение находится перед тем, как его можно получить? Есть ли еще что-либо в этой трассировке стека, или есть внутреннее исключение в ошибке? – Nanhydrin

+0

Это код .NET, а не мой код. Объяснение, которое я имею до сих пор, заключается в том, что я не должен повторно использовать заглушку (ProductResolveService), мне нужно каждый раз закрывать поток запросов и поток ответов. Если это не сделано, то есть таймер (для асинхронных вызовов), который просыпается и пытается получить доступ к потоку запроса/ответа (я не знаю, какой из них), и находит его уже установленным и, следовательно, выбрасывает это исключение. Вызовы, которые я делаю, являются синхронными, и я не знаю, почему 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); 
        } 
    } 
    

 Смежные вопросы

  • Нет связанных вопросов^_^