Solved

.NET BackgroundWorker Multithreading

Posted on 2011-03-04
12
1,029 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
  • 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
 
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
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
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

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Here I am going to explain creating proxies at runtime for WCF Service. So basically we use to generate proxies using Add Service Reference and then giving the Url of the WCF service then generate proxy files at client side. Ok, what if something ge…
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

760 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

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now