Solved

.NET BackgroundWorker Multithreading

Posted on 2011-03-04
12
1,034 Views
Last Modified: 2013-12-17
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
0
Comment
Question by:Thomasian
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 6
12 Comments
 
LVL 23

Expert Comment

by:wdosanjos
ID: 35058466
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.
0
 
LVL 22

Author Comment

by:Thomasian
ID: 35063507
>>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?
0
 
LVL 23

Expert Comment

by:wdosanjos
ID: 35070078
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
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 22

Author Comment

by:Thomasian
ID: 35076307
>>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?
0
 
LVL 23

Expert Comment

by:wdosanjos
ID: 35078068
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.
0
 
LVL 22

Author Comment

by:Thomasian
ID: 35078836
>>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?
0
 
LVL 23

Expert Comment

by:wdosanjos
ID: 35082866
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.
0
 
LVL 22

Author Comment

by:Thomasian
ID: 35083459
>>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.
0
 
LVL 23

Expert Comment

by:wdosanjos
ID: 35103617
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.
0
 
LVL 22

Author Comment

by:Thomasian
ID: 35103699
>>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?
0
 
LVL 23

Accepted Solution

by:
wdosanjos earned 500 total points
ID: 35105314
We did a PoC for a project that required duplex services.  Everything worked well when both service and client were on the same machine, but as soon as we deployed the service to the server things stopped working.  After a couple days of troubleshooting, we identified that the client's machine firewall was blocking the callbacks from the service.  It's just a matter of opening the port on the client, but that was not an option in our case.

Basically the service does not reuse the connection from the client, so the service creates a new connection to the client on another port.  We tried with NetTcpBinding and WSDualHttpBinding with the same results.

More here. Note the client configuration section on both samples.
http://msdn.microsoft.com/en-us/library/ms752250%28v=VS.90%29.aspx
http://msdn.microsoft.com/en-us/library/ms752216.aspx

Silverlight clients have a PollingDuplexHttpBinding that uses a single communication channel, but unfortunately that's only available in Silverlight.

We may have missed something to make it work, but this summarizes our findings.
0
 
LVL 22

Author Closing Comment

by:Thomasian
ID: 35113831
Thanks for all your help.
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article describes relatively difficult and non-obvious issues that are likely to arise when creating COM class in Visual Studio and deploying it by professional MSI-authoring tools. It is assumed that the reader is already familiar with the cla…
Parsing a CSV file is a task that we are confronted with regularly, and although there are a vast number of means to do this, as a newbie, the field can be confusing and the tools can seem complex. A simple solution to parsing a customized CSV fi…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…
How to Install VMware Tools in Red Hat Enterprise Linux 6.4 (RHEL 6.4) Step-by-Step Tutorial

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question