Juan
Juan

Reputation: 15715

Is it OK to use Control.Invoke instead of using a lock?

I'll have a database object that can be accessed from multiple threads as well as from the main thread. I don't want them to access the underlying database object concurrently, so I'll write a set of thread safe public methods that can be accessed from multiple threads.

My first idea was to use a lock around my connection such as lock(oleDbConnection), but the problem is that I would have to lock it for the main thread since is one more thread that can access it. Which would mean rewriting lots of code.

But, since these threads and the main thread wont access the database very often, how about just using some of my control's (maybe the main form's) Invoke method every time I call any of the database methods from another thread. This way, as far as I understand, these methods would be never called concurrently, and I wouldn't need to worry about the main thread. I guess the only problem would be degrading performance a little bit, but as I said, the database is not accessed that often; the reason why I use threads is not so that they can access the database concurrently but so that they can perform other operations concurrently.

So does this sound like a good idea? Am I missing something? Sounds a bit too easy so I'm suspicious.

Upvotes: 3

Views: 170

Answers (3)

L.B
L.B

Reputation: 116108

Why don't you try to use Connection Pool. Every thread can do its work with a different DB connection and send the result to main thread with Invoke. Connection Pooling is a very common approach used in Servers.

See Using Connection Pooling with SQL Server

Upvotes: 1

Fredrik Mörk
Fredrik Mörk

Reputation: 158289

I would definitely go for the lock. You typically want the UI thread responsive when performing operations that may take time, which includes any sort of DB access; you don't know whether it's alive or not for instance.

Also, the typical way to handle connections is to create, use and dispose the connection for each request, rather than reusing the same connection. This might perhaps solve some of your concurrency problems.

Upvotes: 3

Jon
Jon

Reputation: 437336

It sounds like it would work AFAIK, but it also sounds like a really bad idea.

The problem is that when writing lock you are saying "I want this code to be a critical section", whereas when writing Invoke you are saying "I want this to be executed on the UI thread". These two things are certainly not equivalent, which can lead to lots of problems. For example:

  1. Invoke is normally used to access UI controls. What if a developer sees Invoke and nothing UI-related, and goes "gee, that's an unneeded Invoke; let's get rid of it"?
  2. What if more than one UI thread ends up existing?
  3. What if the database operation takes a long time (or times out)? Your UI would stop responding.

Upvotes: 4

Related Questions