I need to use a backgroundworker for a progress bar in wpf, and I'm new to C#. I've read a lot about them, and I have seen that I can create a backgroundWorker, and move the logic that needs to be tracked into a DoWork method, but I can't seem to separate the logic. Any help is appreciated.
EDIT This is a problem I'm actually having from a much larger program. I understand that having a background working for multiplying numbers would be a bad idea. This is just the smallest problem I could come up with that shows what issues I'm having./EDIT
The program is just taking two groups of numbers and multiplying them, but I'd like a progress bar in a separate thread that updates the same time as a MessageBox showing my percentage done, and a textBlock being updated with the values.
MainWindow.xaml.cs
namespace backgroundWorkersWPF
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
double[] group1 = { 1, 2, 3, 4 };
double[] group2 = { 5, 6, 7, 8 };
double multipliedNumbers = 0;
double totalCount = group1.Count() * group2.Count();
double percentageDone = 0;
double steps = 0;
foreach (double x in group1)
{
foreach (double y in group2)
{
multipliedNumbers = x * y;
txtBlock.Text = multipliedNumbers.ToString();
steps++;
/*I need this part in a separate thread, but I don't know
how to easily move this log to a DoWork method without moving everything.*/
percentageDone = steps / totalCount * 100;
progBar.Value = percentageDone;
/*So, if the above part were in a separate thread,
hopefully I would see my MainWindow with a textblock showing the
current multiplication value, a messagebox that reports a numerical value
for the percentage, and a progress bar that changes percentage every time
I close the messagebox. */
MessageBox.Show(percentageDone.ToString());
}
}
}
}
}
MainWindow.xaml
<Window x:Class="backgroundWorkersWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBlock Name="txtBlock"/>
<ProgressBar Height="20"
Width="Auto"
Minimum="0"
Maximum="100"
Name="progBar"/>
</Grid>
</Window>
So to recap, what happens now, is that since everything is on a single thread, my MessageBox's show up, and count up the percentage completes, and then once it hits 100%, it opens the MainWindow and shows a full progress bar, and the textBlock shows the answer to the last two numbers that were multiplied.
What I would like to happen, is have the progress bar run in a separate thread, and everything else stay in the current thread.
I assumed I needed to create a BackgroundWorker, and somehow send the updated percentage complete values to it, but I've only been able to find simple examples of background workers where you move all of your logic into them.
EDIT To clarify, I said that I only want the progress bar in the new thread, but I don't mind if something else, like calculations go in the new thread as well. I just haven't been able to add a background worker without messing up the program royally, or moving ALL of the logic to another thread. I'll add some code to show the types of mistakes I've done in the past, and what I don't want./EDIT
I don't think this is a duplicate because... I don't think this is a duplicate because I'm not asking How to set up a BackgroundWorker, I'm asking how I should separate the logic for it. For example.
I have a nested for loops. It would be simple for me to create a BackgroundWorker and have my DoWork method just have both of the for loops inside of it. But there is logic inside of those loops that I don't want on the separate thread. I'm new to this, so I may be asking the question incorrectly, but I feel as if asking how to separate this logic is a different question than how to use a background worker.
EDIT
I found a solution that works for me. I know this is currently marked as duplicate, but I'm going to add my solution anyway, just in case someone stumbles across this also trying to figure out C# threading.
To answer my question, separating the logic is as simple as creating new functions. I really didn't understand how background workers worked, was my problem. I wasn't sure how to partition out that data I needed in the background. I found my solution while learning more about Async/Await. Async/Await makes more sense to me, so it was easier to understand, and as it turns out, that should be used over BackgroundWorkers in most cases it seems. So here's my solution. Hopefully this gets opened back up eventually.
MainWindow.xaml
<Window x:Class="backgroundWorkersWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBlock Name="txtBlock"/>
<ProgressBar Height="20"
Width="Auto"
Minimum="0"
Maximum="100"
Name="progBar"/>
<TextBlock Name="percentage"
VerticalAlignment="Center"
HorizontalAlignment="Center"
/>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace backgroundWorkersWPF
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
double[] group1 = { 1, 2, 3, 4 };
double[] group2 = { 5, 6, 7, 8 };
//Now the work I wanted is going to an async function. And the data I need in the main thread is returned using IProgress<>
doWork(group1, group2);
}
private async void doWork(double[] group1, double[] group2)
{
double percentageDone = 0;
double steps = 0;
double multipliedNumbers = 0;
double totalCount = group1.Count() * group2.Count();
foreach (double x in group1)
{
foreach (double y in group2)
{
multipliedNumbers = x * y;
txtBlock.Text = "Multiplied Numbers: " + x + " * " + y + " = " + multipliedNumbers.ToString();
steps++;
var progress = new Progress<int>(updateProgressBar);
await System.Threading.Tasks.Task.Factory.StartNew(() => calculatePercentage(steps, totalCount, percentageDone, progress));
}
}
}
private void calculatePercentage(double steps, double totalCount, double percentageDone, IProgress<int> progress)
{
percentageDone = steps / totalCount * 100;
progress.Report((int)percentageDone);
MessageBox.Show(percentageDone.ToString());
}
private void updateProgressBar(int percentageDone)
{
progBar.Value = percentageDone;
percentage.Text = percentageDone.ToString() + "%";
}
}
}
/EDIT