我想解決我的一個智能設備項目(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(這是我重現此異常的方式)。
任何有關這方面的幫助將高度讚賞,因爲我幾天來一直在試圖解決這個問題。
感謝 塞特希
你有沒有確定究竟在何處的錯誤是從你的代碼來嗎?它是否來自getResolvedEpcs的調用,因爲消息在被訪問之前被丟棄?有沒有更多的堆棧跟蹤,或者有錯誤的內部異常? – Nanhydrin
這是從.NET代碼,而不是從我的代碼。到目前爲止,我的解釋是我不應該重用存根(ProductResolveService),我需要每次關閉請求流和響應流。如果沒有這樣做,那麼會有一個Timer(用於異步調用)喚醒並試圖訪問請求/響應流(我不知道哪一個),並發現它已經處理,因此會拋出此異常。我所做的調用是同步的,我不知道爲什麼Timer仍在使用中。 – Senthil
錯誤只發生在您停止或僅僅是隨機發生之後? – Nanhydrin