c# - Access Violation Exception in Unmanaged Code when using OdbcDataAdapter.Fill in Background Thread -
i experimenting threads try , learn bit them. wrote little wpf app starts uses background thread poll odbc source on interval, retrieving data datatable via odbcdataadapter.fill , writing csv file.
every often, app encounters accessviolationexception. timing varies, can run few days before encountering it, other times day. far has not ever happened result of ui interaction.
the thread (loggingthread in stack trace) have mainwindow control via calls myapp manages loggingthread via manualresetevents , cancellationtokensource. loggingthread runs continuous loop managed aforementioned manualresetevents.
i've used dataadapter in other single-threaded projects before, guess how i'm handling loggingthread that's setting conditions exception occur, because polling code quite simple:
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) } { adapter.dispose(); conn.close(); conn.dispose(); } } conn.close(); } }
what cause this? there mitigating action can take avoid it?
let me know if need other code snippets more understand this.
the exception details:
exception info: system.accessviolationexception stack: @ system.data.common.unsafenativemethods.sqlmoreresults(system.data.odbc.odbcstatementhandle) @ system.data.odbc.odbcstatementhandle.moreresults() @ system.data.odbc.odbcdatareader.nextresult(boolean, boolean) @ system.data.odbc.odbcdatareader.close(boolean) @ system.data.odbc.odbcdatareader.dispose(boolean) @ system.data.common.dbdatareader.dispose() @ system.data.common.dbdataadapter.fillinternal(system.data.dataset, system.data.datatable[], int32, int32, system.string, system.data.idbcommand, system.data.commandbehavior) @ system.data.common.dbdataadapter.fill(system.data.datatable[], int32, int32, system.data.idbcommand, system.data.commandbehavior) @ system.data.common.dbdataadapter.fill(system.data.datatable) @ myapp.loggingthread.pollserver(system.data.datatable) @ myapp.loggingthread.logginghandler() @ myapp.myapp.<startprocessing>b__0() @ system.threading.threadhelper.threadstart_context(system.object) @ system.threading.executioncontext.runtrycode(system.object) @ system.runtime.compilerservices.runtimehelpers.executecodewithguaranteedcleanup(trycode, cleanupcode, system.object) @ system.threading.executioncontext.runinternal(system.threading.executioncontext, system.threading.contextcallback, system.object) @ system.threading.executioncontext.run(system.threading.executioncontext, system.threading.contextcallback, system.object, boolean) @ system.threading.executioncontext.run(system.threading.executioncontext, system.threading.contextcallback, system.object) @ system.threading.threadhelper.threadstart()
edit:
here logginghandler() method referenced in stack trace, maybe it'll help.
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); } }
the using statement works on disposable objects. result...
using (odbcconnection conn = new odbcconnection(this.connstr)) { //... }
the using statement translates to:
odbcconnection conn = null; try { conn = new odbcconnection(this.connstr); // other code } { if (conn != null) conn.dispose(); }
your multiple , unnecessary calls dispose() may present problem. calling close() on connection after has been disposed in nested try / block. don't believe full story. more code necessary determine other issue(s).
Comments
Post a Comment