Click here to Skip to main content
15,883,535 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am a WPF and C# thread programming newbie. I have a C# WPF application that requires to upload local big files to remote server (Windows OS) concurrently (thread). Please advise.

I have some questions:

1. For multiple threading in C#, I should choose await/async/Task (C# version 5) or BackgroundWorkder approach? Which approach is the best?

2. Which WPF widget(s)/control(s) I should use for uploading UI and function?

Thank you in advance.
Posted

1 solution

Yes, you need to use multiple threads, but perhaps not too many. It depends on a number of factors. If you have many connections which are slow enough, but the server is not a bottleneck, you always improve the throughput, even if use more threads that the number of CPUs * cores in your system. This is because each thread spends time in the wait state and then does not overuse the CPU time. From the other hand, imagine that all threads work with the connection to the same server, which is itself slow, so it presents the bottleneck, not the traffic in between. In this situation, you simply add some load to both the server and your system, not improving the degree of parallelism. Finally, imagine the simplest situation, when you simply run several threads in parallel. If you create more threads then cores, you also don't actually work really in parallel, because threads start sharing the same resource. You need to analyze all these scenarios before making final decisions; experimenting will also be helpful, but accurate timing needs deep understanding of it.

Now, I would reject BackgroundWorker; this is a good solution in a pinch. Creating a thread through its constructor is also not so good because of unwanted overhead of the creation; thread pool is better but the number of threads is limited. I usually advice a very different way. Create some fixed number of threads (it can change, but through reading some configuration parameters, not changing thereafter during the rest of the lifetime). Then you can reuse those thread when uploading starts, keeping each one in a wait thread using EventWaitHandle. You can start with the very convenient concept of a thread wrapper I introduced:
How to pass ref parameter to the thread[^],
Change parameters of thread (producer) after it is started[^],
MultiThreading in C#[^].

Also, I described the techniques of reusing and throttling the threads and controlling them in my past answers:
Running exactly one job/thread/process in webservice that will never get terminated (asp.net)[^],
Making Code Thread Safe[^],
pause running thread[^],
ManualResetEvent and AutoResetEvent in Thread[^].

Now, shall you use await/async/TPL (tasks)? This is a controversial subject. These technologies are new and very advanced. They are good in many cases, but I have serious arguments in favor of using explicit threads and synchronous (blocking) API, when it comes to your case, network communications, and other similar tasks. Why? In brief, because it makes code more straightforward and controllable, and because you keep reusing of the same thread synchronization techniques, which don't depend on application-specific asynchronous API. Please see my past answers on the topic:
Async Await Multiple Telnet Servers[^],
TCP Socket - Send and receive question[^],
TcpListener, TcpClient, Ping in Visual Basic 2005[^],
problem in multithreading ? !!![^].

Nevertheless, you can consider using await/async approach, but I don't recommend TPL, where thread control is done automatically. Why? Because, in your case, you have some deterministic fixed setting, such as: one TCP channel per thread. Anyway, you finally decide.

Finally, you don't need any WPF-specific controls or other components, except the usual one (buttons, some input controls, etc.) It's much better to do all the network communication work in those thread using non-component classes, such as System.Net.WebRequest (abstract, concrete runtime type is chosen by the URL), System.Net.HttpWebRequest, System.Net.FtpWebRequest… I don't know what your services are, so decide by yourself. If you clarify that and ask some follow-up questions, I'll gladly try to answer them, too.

The only UI-related issue is the synchronization of the thread operation with UI. You may need to notify UI of the progress, status, results of all the tasks. But — уou cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Windows.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).

You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

See also more references on threading:
How to get a keydown event to operate on a different thread in vb.net[^],
Control events not firing after enable disable + multithreading[^].

—SA
 
Share this answer
 
v2
Comments
Thomas Benz 19-Sep-14 13:37pm    
Hi Sergey, thank you for your kind ideas.
Sergey Alexandrovich Kryukov 19-Sep-14 15:06pm    
You are welcome.
Will you accept the answer formally (green "Accept" button)? In all cases, your follow-up questions will be welcome, and other can add their contributions.
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900