49

I was wondering how you would use the TransactionScope class in the correct way when you are dealing with multithreading?

We create a new scope in our main thread and then we spawn off a couple of worker threads and we want these to participate in the main scope, so that for example the rollback is called on each worker if the scope is never completed.

I read something about TransactionScope using the ThreadStaticAttribute internally which made the above impossible / very difficult - could someone verify either way? If we run our code in a synchronized fashion then the rollbacks work, i.e the inner transactions are able to participate in the main transaction, but not if we switch over to a threaded execution.

Jeff B
  • 8,572
  • 17
  • 61
  • 140
TheCodeJunkie
  • 9,378
  • 7
  • 43
  • 54
  • 1
    Good question; this is a scenario I had simply dismissed as "don't do that", but upon investigation, there is support via DependentTransaction. I learnt something, thanks. – Marc Gravell Mar 23 '09 at 14:38
  • This is probably really obsolete info now, considering that what's described here is now considered a bug, and TransactionScope has an new option allowing it to flow across async awaits, which would have to support multi-threading. https://particular.net/blog/transactionscope-and-async-await-be-one-with-the-flow – Triynko Jul 02 '18 at 15:12

2 Answers2

34

See MSDN:

You should also use the TransactionScope and DependentTransaction class for applications that require the use of the same transaction across multiple function calls or multiple thread calls.

So maybe look into DependentTransaction - in particular, there is a worker thread example, here.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • I also found these two blog posts useful: http://www.pluralsight.com/community/blogs/jimjohn/archive/2005/04/14/7332.aspx and http://www.pluralsight.com/community/blogs/jimjohn/archive/2005/05/01/7923.aspx – Roman Starkov Oct 11 '09 at 13:11
  • 2
    it's apity, that blog is not found now – Kiquenet Mar 05 '12 at 10:28
  • @Kiquenet In cases like [these](http://web.archive.org/web/2/http://pluralsight.com/community/blogs/jimjohn/archive/2005/04/14/7332.aspx) [two](http://web.archive.org/web/2/http://pluralsight.com/community/blogs/jimjohn/archive/2005/05/01/7923.aspx), there's (almost) always the [wayback machine](https://en.wikipedia.org/wiki/Wikipedia:Using_the_Wayback_Machine#Latest_archive_copy) – Evgeniy Berezovsky Aug 29 '13 at 05:32
  • 7
    .net 4.5.1 introduced a more elegant solution, using TransactionScopeAsyncFlowOption.Enabled . See more here http://stackoverflow.com/a/17527759/43515 – Leon van der Walt Feb 04 '14 at 15:09
19

This is correct: the TransactionScope class uses the Transaction.Current property that stores its value in the field, which is marked with the ThreadStatic attribute.

The ThreadStatic attribute makes sure that the field value gets thread affinity, i.e. it has unique value in each thread. It's the recommended approach to share data within a thread. It's also known as Thread Local Storage (TLS).

The TransactionScope class just defines a transaction context in the current thread. It doesn't mean, however, that your code must accomplish all the job in that thread. I could imagine a complex calculation algorithm that uses multiple threads.

Jeff B
  • 8,572
  • 17
  • 61
  • 140
Michael Damatov
  • 15,253
  • 10
  • 46
  • 71