Link to home
Start Free TrialLog in
Avatar of Thomasian
ThomasianFlag for Philippines

asked on

.NET BackgroundWorker Multithreading

I have a formless application which acts as a WCF server for several client apps. The concurrency mode of the service is set to single.

The server keeps a collection of transaction objects (w/ fields starttime, endtime, etc..) and the client apps are used to modify and monitor the transactions. e.g. A client can send a "New Transaction" command to add a new transaction to the server, and the changes made would be sent to all connected clients.

Here's what I plan to do:
1. When a client first connects to the server, the server checks the login information of the user and returns the login status (i.e. "successful" or "incorrect password", etc). The server will then create a (deep) copy of the collection and send it to the client asynchronously using background worker.

2. When a client sends a command (e.g. "New Transaction") to the server, the server again validates the command and parameters, then returns a response ("successful"/"invalid"). The transactions that are affected by the command will then be send to all the clients again by making a deep copy and using background worker.

3. I plan to have about 5 backgroundworker objects for maybe 50 or more clients. I will have a "SendList" which stores the data to be send and to which client. The backgroundworker will get the next job from the SendList after it finishes its current job.

Now here are my questions:
1. Aside from locking the transaction collection when creating a deep copy, is there anything else I need to consider for multithreading?
2. Do I need to lock the SendList when adding and retrieving data?

Any other suggestions to implement this are also welcome.

TIA
Avatar of wdosanjos
wdosanjos
Flag of United States of America image

1. I you need to check all resources that will be shared among the threads for potential race conditions. Even reads from your transaction collection can fail if other threads are updating the collection.

2. Yes, SendList must be synchronized (locked) for updates and reads.
Avatar of Thomasian

ASKER

>>you need to check all resources that will be shared among the threads for potential race conditions.

If I have the WCF's concurrency set to single, does that mean that the only part I need to consider as multithreading is the "DoWork" event of the background worker, is that correct? The events raised by the background would be on the same thread as my main thread right?
WCF Single Concurrency only allows one request to be processed at a time, that seems to conflict with your multi-threading requirement.

Regarding the following statement, how does the background worker sends the data back to the client?

The server will then create a (deep) copy of the collection and send it to the client asynchronously using background worker.

BTW, BackgroundWorker is a threading class better suited for the presentation layer (WinForms, WPF).  For server threading, you should consider using the ThreadPool class.

    http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx
>>WCF Single Concurrency only allows one request to be processed at a time, that seems to conflict with your multi-threading requirement.
I was thinking of using single concurrency because using multiple concurrency on my case doesn't seem to make any sense. For every client call, I will need to read/write to the collection, so a call from a client can't be processed until a previous call is done. So no multi threading actually occurs even when I set it to multiple concurrency. Or did I misunderstood anything?

>>Regarding the following statement, how does the background worker sends the data back to the client?
By using callbacks.


>>BTW, BackgroundWorker is a threading class better suited for the presentation layer (WinForms, WPF).  For server threading, you should
>>consider using the ThreadPool class.
I need to be able to guarantee the order in which data is received by a client.

e.g. When a client first connects to the server, the "job" of sending the collection is queued on the treadpool. But while sending the data, a new transaction is added. The next "job" is then to send the update to all connected client. Since I'm sending everything asynchronously, I'm afraid that a client might not receive the data in the correct order. i.e. A client receives the update (new transaction) first before receiving the collection.

How do I make this work using ThreadPool?
I'm not sure I'd use single concurrency, but you have a better understanding of the requirements.

Even with BackgroundWorker there is no garantee that threads will execute in a particular order, unless you code for that.  In your case, you need to keep track of each client's state, so that new transactions are not sent to clients unless they have received the collection.

Managing the callbacks can be tricky, because clients can become unreachable for a short time and miss a new transaction callback.  In those cases, you would need to keep track also of what transactions each client have received.  BTW, you might have to open firewall ports on the client for callbacks to work.

An alternative design is for each client to poll the server for new transactions on a regular basis, this could simplify synchronization of new transactions and avoid opening firewall ports.
>>Even with BackgroundWorker there is no garantee that threads will execute in a particular order, ...

I was going to write my own code for this, but I just found out about reliable session which seems to be able to guarantee the order in which data is received.


>>Managing the callbacks can be tricky, because clients can become unreachable for a short time and miss a new transaction callback.

Will I still have this problem when I enabled reliable session?


>>BTW, you might have to open firewall ports on the client for callbacks to work.

I don't understand. Why would firewall be an issue for callbacks? Callbacks won't be opening additional ports, would it?


>>An alternative design is for each client to poll the server for new transactions on a regular basis, ...

If reliable session is able to guarantee that each message is received and in the correct order, is the polling method still recommended?
I don't have experience working with Reliable Session, but from the documentation it seems to address your issue.

Regarding the firewall, callbacks require the server to initiate the connection to the client.  From a client point of view that's inbound traffic coming on a new port.
>>callbacks require the server to initiate the connection to the client.

Wasn't a connection always present when the client first connects to the server? Btw, I forgot to mention that I am using nettcp and pipe binding, not sure if that would make any difference.
I've used nettcp and wshttp bindings with callbacks, and in both cases the server needs to initiate a new connection with the client.  Unfortunately, I never tried with pipe binding.
>>I've used nettcp and wshttp bindings with callbacks, and in both cases the server needs to initiate a new connection with the client.

I'd like to learn more about this. Does the the server use the same port number to connect to the client? Can you tell me how you verified that?
ASKER CERTIFIED SOLUTION
Avatar of wdosanjos
wdosanjos
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks for all your help.