We were just aborting the background thread, so I tried changing our code to call ISession.CancelQuery(). I noticed a few issues:
1. With Thread.Abort(), our code running the background thread could catch exceptions and detect ThreadAbortException. With ISession.CancelQuery, we get a database-vendor-specific exception message -- using SQL Server, we get something like "SqlException: operation canceled by user". This is a lot messier to detect. It would be nice if NHibernate wrapped this exception in a specific, database-vendor-independent one of its own to clearly and reliably indicate that the query was canceled.
2. I ran into the case where the query I tried to cancel had actually completed at the database level by the time I attempted to abort, so ISession.CancelQuery() had no effect. NHibernate had started the process of instantiating the tens of thousands of entities returned by the query. This ate up a lot of local processor time, which I couldn't cancel out of.
Can someone explain why it's not a good idea to just abort the worker thread in order to cancel a query? If it's just that the query may still be running on the database server, then we'll try setting a timer after CancelQuery() returns, and if the worker thread isn't done within a few seconds more, then abort the worker thread. This should limit the waste instantiating a ton of entities from an already-completed database query ...
|