Design Ideas for Parallel Processing

I have a series of calculations that need to be processed - the calculations and the order of their launch are determined by the user in the user interface.

If they just ran one after another, that would not be too difficult. However, some calculations must be processed simultaneously, and all calculations must be able to individually pause at any time. I also need to be able to reorder orders or add new calculations for processing at any time. So everything I do should be flexible enough to handle this.

In the user interface, imagine a list (queue, if you want) of usercontrols - each user control displays a calculation name and a pause button. And I can add calculations to this list at any time during processing.

What is the best way to do this?

Do I have to run each calculation in my thread? If so, how do I keep a list of running processes? How to pass a queue to the processor of calculations? How can I guarantee that every time the queue changes (new order or new calculation), the calculation processor will be informed about this?

My initial thoughts were as follows:

  • CalcProcessor class
  • CalcCalculation class

There are 2 Lists of CalcCalculations . One of them is a โ€œqueueโ€, as shown in the user interface (perhaps a pointer to it or some other way to ensure its updating in real time), and the other is a list of current calculations.

Somehow I need to run CalcCalculation in my thread to handle the calculation and be able to handle any pause events. Therefore, I need to somehow pass the information about the Pause button pressed in the user interface to the CalcProcessor object, and then to the correct CalcCalculation .

Edit in response to David Hope:

Thanks for your reply.

  • Yes, there are n calculations, but this can change at any time due to the ability to add additional calculations for processing in the user interface.

  • In any case, they do not need to exchange data. The application will indicate how many of them should be started at the same time (i.e. 10 at any time, for example, the first 10 in the queue, and when 1 ends, the next calculation in the queue will start processing).

  • The calculation will include obtaining data from some data source โ€” it can be a database or a file, as well as analyzing and performing some calculations on this data. When I say that the calculation should be suspended, I do not mean to suspend the flow ... I mean (for example, since I have not written this part of the application yet) if it reads line by line from the database and do whatever then live calculations, stopping at the end of processing the current line ... and continuing when the pause button is not decoupled in the user interface - which can be done with something as primitive as the while (notPaused) loop, which I can get Pause information from the user interface to the stream.

+4
source share
5 answers

There are a few questions here:

How to synchronize user interface and model?

I think you got it back. Your model should not have a โ€œpointerโ€ to the queue that you are showing in the user interface. Instead, the queue should be in your model, and you should use data binding along with INotifyPropertyChange and ObservableCollection to display the queue in the user interface. (At least as done in WPF.)

Thus, you can manipulate your queue directly from your model, and it will automatically be displayed in the user interface.

How to start and control calculations?

I think Task perfect for this. You can run Task with Task.Factory.StartNew() . Since it seems like your Task will take a long time, you can use TaskCreationOptions.LongRunning . You can also use Task to find out when the calculation finishes (or if it did not work with an exception).

How to suspend calculations?

You can use ManualReserEventSlim . It will usually be installed, but if you want to pause the launch of Task , you would Reset() it. To calculate, you must periodically call Wait() on this event. It is impossible to reasonably suspend a thread without collaboration based on that thread.

If you used C # 5.0, the best approach would be to use something like PauseToken .

+2
source

In Framework 4.5, the answer here is the Async API, which eliminates the need for thread control. See the async / wait keywords for more details.

From a broader perspective, the CalcProcessor class is a good idea, but I think the Task object will be sufficient to replace your CalcCalculation class. A processor can simply list tasks. If necessary, the processor can set queue management methods, as well as return information about its status. When your application finally reaches the state where it should have results, you can use the AwaitAll method to block the CalcProcessor thread until all tasks are complete.

Without additional information about the actual purpose, it is difficult to give the best advice here.

0
source

You can use the Watcher Pattern to display the results in the user interface and revert changes to the Processor. State and Command templates will help you start, pause, cancel calculations. These templates have great answers to your design questions. Concurrency is still a problem, they do not respond to problems with multiple threads, but they open up an easier way for thread management.

0
source

I suggest that you do not violate the problem far enough, which is the reason that you are upset.

You need to start small and build from there. You mention, but do not define your actual requirements, but they seem ...

  • Need to be able to run? N? calculations
  • Some should be launched at the same time (does this mean that they are exchanging data, if so, how are you going to share the data)
  • It should be able to pause the calculation (do not use Thread.Suspend, since it potentially leaves the thread in an unstable state, especially bad if you use data), so you will need to create breakpoints in each calculation. You also need to think about how you are going to report a pause / malfunction in the calculation

As for the methods, there are several ...

Themes are an obvious choice, but also require careful maintenance (start, pause, stop, etc.)

You can also use BackGroundWorker or perhaps Parallel.ForEach

BackGroundWorker provides a framework for canceling a worker and making progress (which may be useful).

My recommendation is to go with BackGroundWorker, potentially subclass it to add the Pause / Resume features you need. Determine how you intend to manage data sharing (at least use a lock to protect against simultaneous access).

You may find BackGroundWorker too strict, and you need to go with Threads, but I can usually avoid it.

If you post more specific requirements or samples of what you have tried and not worked, I will be happy to help more.

0
source

For a queue, you can use the heap data structure (priority queue). This will help prioritize your tasks. You should also use a thread pool for efficient calculation. And try to divide the tasks into small parts.

0
source

All Articles