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

使用OdbcDataAdapter时,非托管代码中出现访问冲突异常.请填写后台线程

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对象。。。