Search code examples
winformsmultithreadingc#-4.0task-parallel-library

Adding controls to winform while allowing user to enter input


I have a WinForms data entry form that will have upwards of 1500 questions. I have the questions broken into sections, and each section will have an unkown number of questions. Each section is its own user control and has rows (2 panels, 2 labels, a textbox, and another user control) created and added dynamically for each question. The section controls are then added to the form.

My problem is that the process takes a lot of time, even with using TPL (Task Parallel Library). I would ultimately like to create/add the controls and allow the user to start entering data at the same time. The controls are going into a scrollable panel. While the user is entering data, that data will need processed on a local database...so more threading could be necessary.

I have tried working with TPL, which I am new to, by having all the controls added to a list during processing and then sorted and added to the form after the Parallel.ForEach was complete...takes about 20 seconds for over 1200 questions.

I also tried utilizing a BackgroundWorker component. Using the BWC seems to be the faster of the two, but there is a race condition for the ProgressChanged() eventhandler and not all controls get added...not to mention the way the form looks with all the rerendering.

Am i just using TPL wrong? What's the best way to go about this? Is there another way or do I just make the user stick out the wait?

Thanks


Solution

  • Am i just using TPL wrong? What's the best way to go about this? Is there another way or do I just make the user stick out the wait?

    Most likely, you can use TPL, and get the same response time as BW, but a nicer API for this type of operation.

    The trick here is to get a TaskScheduler setup for UI interaction, and then use the Task class to push the controls back onto the UI thread as they're ready. I have a blog post on this specific subject which shows how to get a TaskScheduler setup to use with UI threads.

    However, I would recommend keeping these in memory and pushing them in batches, to avoid constantly re-rendering the UI. This is likely to be an issue no matter what you're doing.

    That being said - I'd question your overall visual design here - if you're trying to display over 1200 questions to the user, some form of paging is probably a much nicer approach than a huge scrollable container. If you page these, you could load and process the first few (which is probably near instantaneous, since you mentioned you can process about 50 questions/second), and then continue loading the others after the first few questions have been displayed.