Thomasian
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
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
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?
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?
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
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
ASKER
>>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 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, 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.
ASKER
>>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 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.
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.
ASKER
>>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.
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.
ASKER
>>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?
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
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
ASKER
Thanks for all your help.
2. Yes, SendList must be synchronized (locked) for updates and reads.