0

I have the following problem:

I want to write a WPF application which needs to do heavy multithreaded computation in the background. Right now I just add Threads to the Threadpool and if the find the right answer I call the Dispatcher.BeginInvoke methode to update the UI. So at times I have more than 1000 Threads in my Threadpool which wait to be excecuted and the UI freezes.

So I think I need a way to be able to have a fast Queue which runs only a fixed number of Threads while keeping one thread for the UI which always is at idle, so the user can still interact with it.

Anyone got an good Idea on how to solve this? Or do I have to implement a ThreadQueue myself which does excactly that?

My Current Code in Pseudo Code:

WPF Aplication

init(){
    BackgroundWorker.dosomething();
}
updateUI(data){
    Dispatcher.BeginInvoke(()=>{
        UIFrame = data
    })
}

BackgrondWorker

dosomething(){
    for(i = 0; i < 50000; i++){
        ThreadPool.QueueUserWorkItem(dosomethingElse);
    }
}
dosomethingElse(){
    //Heavy computation with data as a result
    if(foundsomthing){
        WPF.updateUI(data);
    }
}
Schweini
  • 17
  • 2
  • 3
    There's already a thread reserved for the UI. I think your issue is with something else. – Palle Due Jan 05 '22 at 09:04
  • You may also want to use Tasks instead of Threads. Take a look at [Asynchronous programming with async and await](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/). – Clemens Jan 05 '22 at 09:16
  • Related: [Execute certain background Tasks in separate ThreadPool to avoid starvation to critical Tasks executed in main thread](https://stackoverflow.com/questions/60899507/execute-certain-background-tasks-in-separate-threadpool-to-avoid-starvation-to-c) – Theodor Zoulias Jan 05 '22 at 10:13
  • I think your approach is wrong here. 1: you are using frame, so good bye to context inheritance (and if you are using it for Navigate method, start learning about ContentControl), 2: you are creating UI elements on background threads? why not just use data templates? – XAMlMAX Jan 05 '22 at 13:24

1 Answers1

3

Running a thousand background threads are likely quite inefficient, both due to added memory usage and due to switching overhead.

A simple way to fix it would be to run a parallel loop on a background thread. I.e.

// On UI thread:
var backgroundTask = Task.Run(dosomething);
...
private void dosomething(){
    Parallel.For(0, 50000, dosomethingElse);
}
private void dosomethingElse(int index){
    ...
}

This will limit the number of threads used to something more reasonable, and should probably result in better performance. You can also limit the max number of threads used to always leave one or more cpu core to do other things, like updating the UI. If the amount of work done in each iteration is small, you can use partitioning to reduce the threading overhead. You might also want to take a look at the DataFlow APIs

JonasH
  • 28,608
  • 2
  • 10
  • 23