使用OdbcDataAdapter时,非托管代码中出现访问冲突异常.请填写后台线程
本文关键字:异常 线程 后台 访问冲突 OdbcDataAdapter 非托管代码 使用 | 更新日期: 2023-09-27 17:58:06
我正在尝试使用Threads来了解它们。我写了一个小的WPF应用程序,它启动时使用后台线程每隔一段时间轮询ODBC源,通过OdbcDataAdapter将数据检索到DataTable中。填充并写入CSV文件。
应用程序每隔一段时间就会遇到AccessViolationException。时间各不相同,有时在遇到它之前可以运行几天,有时一天就可以。到目前为止,它还没有作为UI交互的结果发生过。
线程(堆栈跟踪中的LoggingThread)将由MainWindow通过调用MyApp来控制它,MyApp通过ManualResetEvents和CancellationTokenSource管理LogingThread。LoggingThread本身运行一个由上述ManualResetEvents管理的连续循环。
我以前在其他单线程项目中成功地使用过DataAdapter,所以我想可能是我如何处理LoggingThread为发生此异常设置了条件,因为轮询代码非常简单:
if (!this._cancelToken.IsCancellationRequested)
{
using (OdbcConnection conn = new OdbcConnection(this.connStr))
{
using (var adapter = new OdbcDataAdapter(this.sql, conn))
{
try
{
int rows = adapter.Fill(table);
}
catch() { // log Exception(s) }
finally
{
adapter.Dispose();
conn.Close();
conn.Dispose();
}
}
conn.Close();
}
}
是什么原因造成的?我是否可以采取一些缓解措施来避免这种情况?
如果您需要其他代码片段来更全面地理解这一点,请告诉我。
异常详细信息:
Exception Info: System.AccessViolationException
Stack:
at System.Data.Common.UnsafeNativeMethods.SQLMoreResults(System.Data.Odbc.OdbcStatementHandle)
at System.Data.Odbc.OdbcStatementHandle.MoreResults()
at System.Data.Odbc.OdbcDataReader.NextResult(Boolean, Boolean)
at System.Data.Odbc.OdbcDataReader.Close(Boolean)
at System.Data.Odbc.OdbcDataReader.Dispose(Boolean)
at System.Data.Common.DbDataReader.Dispose()
at System.Data.Common.DbDataAdapter.FillInternal(System.Data.DataSet, System.Data.DataTable[], Int32, Int32, System.String, System.Data.IDbCommand, System.Data.CommandBehavior)
at System.Data.Common.DbDataAdapter.Fill(System.Data.DataTable[], Int32, Int32, System.Data.IDbCommand, System.Data.CommandBehavior)
at System.Data.Common.DbDataAdapter.Fill(System.Data.DataTable)
at MyApp.LoggingThread.PollServer(System.Data.DataTable)
at MyApp.LoggingThread.LoggingHandler()
at MyApp.MyApp.<StartProcessing>b__0()
at System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
at System.Threading.ExecutionContext.runTryCode(System.Object)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode, CleanupCode, System.Object)
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
at System.Threading.ThreadHelper.ThreadStart()
编辑:
这是堆栈跟踪中引用的LoggingHandler()方法,也许它会有所帮助。
DataTable table = new DataTable();
while (true)
{
this.pauseEvent.WaitOne(Timeout.Infinite);
if (this.stopEvent.WaitOne(0))
{
break;
}
PollServer(table);
if (table != null && table.Rows.Count > 0)
{
WriteData(table);
table.Clear();
}
else
{
table = new DataTable();
}
if (!this._cancelToken.IsCancellationRequested)
{
this.loopingEvent.WaitOne(this.delaySpan);
}
}
using语句仅适用于一次性对象。因此。。。
using (OdbcConnection conn = new OdbcConnection(this.connStr))
{
//...
}
using语句翻译为:
OdbcConnection conn = null;
try
{
conn = new OdbcConnection(this.connStr);
// other code
}
finally
{
if (conn != null)
conn.Dispose();
}
对Dispose()的多次且不必要的调用可能会出现问题。特别是当连接在嵌套的try/finaly块中被释放后,您正在对连接调用Close()。然而,我不相信这是完整的故事。需要更多的代码来确定其他问题。
我遇到了同样的问题,我使用了"使用";但还是失败了。我意识到这是下面的一行,
Using cmd As System.Data.Odbc.OdbcCommand = objConn.CreateCommand()
End Using
我的问题是,为了保持连接的打开,我传递了连接对象,并且我创建了很多ObdcCommand
对象。。。