使用.Net框架4,我在多线程C#代码中获得了System.AccessViolationException,即使我的所有代码都是托管代码。这可能是.Net中的一个错误,因为我一直认为使用.Net意味着无论我做出什么编程错误,都不应该发生AccessViolationException?
我从Visual Studio 2010获得的唯一错误消息是
Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
没有调用堆栈信息(它只是说[External Code]
),即使我打开非托管调试以尝试查看本机调用堆栈,也是如此。
我的应用程序通过公共互联网将多个同时的http调用发送到返回JSON对象的API。所有的调用都是通过我在下面粘贴的AsyncResult类进行的。关于如何解决这个问题的任何建议都是非常受欢迎的。
public class AsyncResult<T> : IDisposable where T : class {
private const int NumPasses = 2; // if Exception thrown on first pass, try again in case it was an internet problem
public readonly System.Threading.ManualResetEvent allDone;
public readonly string method;
public readonly IDictionary<string, object> args;
private readonly RpcClient.CreateWebRequestDelegate cwr_deleg;
private readonly VoidVoidDelegate cb; // to be called when Async operation complete or abandoned
public readonly string LocationDescripForError;
private int m_count; // number of passes. Call should execute on first pass
private bool m_Abort; // mechanism for aborting from outside the object
private int m_Stage; // 0 = waiting for GetRequestStreamCallback, 1 = waiting for GetResponseCallback, 2 or greater = waiting for ReadStreamCallBack
private System.Exception m_exception; // non null if an exception has occurred
private WebRequest request;
private IAsyncResult iasr_GetRequestStream;
private IAsyncResult iasr_GetResponse;
private IAsyncResult iasr_streamRead;
private WebResponse response;
private Stream responseStream;
private const int BUFFER_SIZE = 1024;
private byte[] buffer;
private StringBuilder sb_jsonResponse;
private T result;
public AsyncResult(string method, IDictionary<string, object> args, RpcClient.CreateWebRequestDelegate cwr_deleg, string LocationDescripForError, VoidVoidDelegate cb) {
allDone = new System.Threading.ManualResetEvent(false);
this.method = method; this.args = args; this.cwr_deleg = cwr_deleg; this.LocationDescripForError = LocationDescripForError; this.cb = cb;
m_count = 0; m_Abort = false; buffer = new byte[BUFFER_SIZE]; sb_jsonResponse = new StringBuilder("");
InitiateCallSequence();
}
~AsyncResult() { try { Dispose(); } catch {} }
private void InitiateCallSequence() {
if (m_Abort) return;
m_count++;
m_Stage = 0; m_exception = null; sb_jsonResponse.Clear();
request = cwr_deleg();
iasr_GetRequestStream = (IAsyncResult)request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), null);
}
private void ExceptionHandling(System.Exception Ex) {
if (m_count < NumPasses) {
try {
iasr_GetRequestStream = null; InitiateCallSequence();
if (iasr_GetRequestStream != null) return;
} catch { }
}
m_exception = Ex;
lock (allDone) {
if (!m_Abort) allDone.Set();
}
if (cb != null) cb();
}
private void GetRequestStreamCallback(IAsyncResult asynchronousResult) {
System.Threading.Interlocked.Increment(ref m_Stage);
try {
using (Stream streamResponse = request.EndGetRequestStream(asynchronousResult)) {
if (m_Abort) return;
using (StreamWriter writer = new StreamWriter(streamResponse, Encoding.UTF8)) {
Request call = new Request { Method = method, Id = 1, Params = args };
Convert.Export(call, writer);
}
}
iasr_GetResponse = (IAsyncResult)request.BeginGetResponse(new AsyncCallback(GetResponseCallback), null);
} catch (System.Exception Ex) { ExceptionHandling(Ex); }
}
private void GetResponseCallback(IAsyncResult asynchronousResult) {
System.Threading.Interlocked.Increment(ref m_Stage);
try {
response = request.EndGetResponse(asynchronousResult); // End the Asynchronous response.
if (m_Abort) return;
// Read the response into a 'Stream' object.
responseStream = response.GetResponseStream();
iasr_streamRead = responseStream.BeginRead(buffer, 0, BUFFER_SIZE, new AsyncCallback(ReadStreamCallBack), null);
} catch (System.Exception Ex) { ExceptionHandling(Ex); }
}
private void ReadStreamCallBack(IAsyncResult asynchronousResult) {
System.Threading.Interlocked.Increment(ref m_Stage);
try {
int read = responseStream.EndRead(asynchronousResult); // End the Asynchronous read.
if (m_Abort) return;
if (read > 0) {
sb_jsonResponse.Append(Encoding.ASCII.GetString(buffer, 0, read));
iasr_streamRead = responseStream.BeginRead(buffer, 0, AsyncResult<T>.BUFFER_SIZE, new AsyncCallback(ReadStreamCallBack), null);
} else {
Response<T> jsonResponse = Convert.Import<T>(sb_jsonResponse.ToString());
if (jsonResponse.HasError) {
System.Exception Ex = ReconstituteException(jsonResponse.Error, LocationDescripForError);
ExceptionHandling(Ex);
return;
} else {
result = jsonResponse.Result;
}
responseStream.Dispose();
responseStream.Close();
if (m_count > 1) System.Diagnostics.Trace.WriteLine("AsyncResult success count=" + m_count);
lock (allDone) {
if (!m_Abort) allDone.Set();
}
if (cb != null) cb();
}
} catch (System.Exception Ex) { ExceptionHandling(Ex); }
}
public T GetResult(int millisecondsTimeout) {
bool waitresult = allDone.WaitOne(millisecondsTimeout);
if (waitresult)
return (m_exception == null ? result : null);
else {
Abort();
return null;
}
}
public bool IsError { get { return (m_exception != null); } }
public string ErrorMessage { get {
if (m_exception == null) return string.Empty;
WebException wex = (m_exception is WebException ? (WebException)m_exception : null);
string retval = CoreLogging.ExceptionDescription(m_exception) + " API-NG(" + method + ":" + m_Stage + "): " + m_exception.Message + (string.IsNullOrWhiteSpace(m_exception.Source) ? "" : ", Source=" + m_exception.Source) + (wex == null ? "" : ", Status=" + wex.Status);
return retval;
} }
public int GetStage() { return m_Stage; }
public void Abort() { m_Abort = true; Dispose(); }
public bool IsAborted { get { return m_Abort; } }
public void Dispose() { lock (allDone) { allDone.Dispose(); } }
}