0

To start, I'm new to Threads, never worked with them before, but since the current project is severely impacted by slow runtimes, I wanted to take a peek into multithreading and this post is a question on whether it is possible given my current project, and how I would approach this in its entirety.

To start, you must understand that I have a Windows Form UI, which has a button that, upon clicking, runs an algorithm that generates an image. This is done in 3 steps really: Extracting patterns (if the settings have changed only), running the algorithm and displaying the result bitmap.

The average time spent on each part is as follows: Pattern extraction takes up the biggest chunk, usually 60%+ of the running time. The Algorithm itself takes up 40% of the running time. However, if no settings have been changed, simply re-running won't require the recalculation of the patterns and hence it's way faster. The displaying of the result bitmap, due to the bitmap being rescaled, takes a fixed ~200ms (Which I think can be optimized but IDK how).

The problem I'm having with trying to grasp the threading issue is that the algorithm is based on the patterns extracted from the first step, and the resulting bitmap is dependent on the algorithm.

My algorithm does, however, compute each pixel one by one, so I was wondering if it was possible to, once a single pixel has been calculated, already display it, such that the displaying of the image and the calculation of the others can be done in parallel.

If anything is unclear, please feel free to ask any questions.

Thank you!

GSerum_
  • 57
  • 8
  • You are conflating some concepts here: (Multi-)Threading vs Concurrency vs Parallelism. Also: _"I was wondering if it was possible to, once a single pixel has been calculated, already display it"_ that's actually a _bad_ idea. I _guess_ your biggest concern for the time being is _unresponsiveness_. If you calculate everything on the GUI Thread, your Application "hangs", right? So first step is to do all the calculations on the side and display the result. Then you can go on to optimize further. – Fildor Feb 14 '22 at 12:32
  • @Fildor Yeah I guess that's the idea instead, unresponsiveness. It's not necessarily the problem that the application hangs, but more that the user has to wait for the result. I'm trying to optimize it as much as possible, and thought this could be done through calculating the final bitmap simultaneously with displaying it. – GSerum_ Feb 14 '22 at 13:26
  • 1
    You should post the code you're using, so it will be more clear what *pattern extraction* means in your context and how the Bitmap is being processed. -- In this platform, you cannot show a *partial Bitmap* and *make it quick* at the same time. -- You can always show a ProgressBar that keeps the user informed on the process. Then, it also depends on what the user can do with your app while waiting for this result. If they can do nothing, might as well hang the application. Optimizations are probably possible, depending on the current task and the code you have. – Jimi Feb 14 '22 at 17:03
  • Please show us your code! – Enigmativity Feb 14 '22 at 20:44
  • @Jimi and Enigmativity I would love to share the code but each part is over 1K LOCs, I have however fixed the issue slightly by using GDI instead of direct bitmap to bitmap copying – GSerum_ Feb 15 '22 at 21:44
  • @GSerum_ - You can use pastebin to show us the code. But it would really be useful for you and for us to do a [mcve]. It makes answering so much easier and more relevant. – Enigmativity Feb 16 '22 at 01:11

1 Answers1

1

current project is severely impacted by slow runtime

I would advice that you start with doing some measurements/profiling before doing anything else. It is not uncommon for programs to waste the vast majority of time doing useless stuff. Avoiding such unnecessary work can give a much more performance improvement than multi threading.

The typical method for moving processing intensive work to a background work is using Task.Run and async/await for processing the result. Note that using a background thread to avoid blocking the UI thread is different from doing the processing in parallel to improve performance, but both methods can be combined if needed.

My algorithm does, however, compute each pixel one by one, so I was wondering if it was possible to, once a single pixel has been calculated, already display it, such that the displaying of the image and the calculation of the others can be done in parallel.

Updating the displayed image for every pixel is probably not the way to go, since that would be rather costly. And you are typically not allowed to touch objects used by the UI from a background thread.

One way to manage things like this would be to have a timer that updates the UI every so often, and a shared buffer for the processed data. Once the update is triggered you would have a method that copies the shared buffer to the displayed bitmap, without locks this would not guarantee that the latest values are included, but for simply showing progress it might be good enough.

You could also consider things like splitting the image into individual chunks, so that you can process complete chunks on the background thread, and then put them in a output queue for the UI thread to pickup and display. See for example channel

JonasH
  • 28,608
  • 2
  • 10
  • 23