Multi-threading Report Progress Not Working - c#

I've recently started working with multi-threaded Winform applications and have run up against a problem I don't understand.
Basically, when I try to have a background worker report its progress and that progress comes from a calculation, it is always zero.
//making background worker
BackgroundWorker myJanitor = new BackgroundWorker();
myJanitor.WorkerSupportsCancellation = true;
myJanitor.WorkerReportsProgress = true;
myJanitor.DoWork += new DoWorkEventHandler(cleanContactList);
myJanitor.ProgressChanged += new ProgressChangedEventHandler(myCleaningWorker_ProgressChanged);
myJanitor.RunWorkerAsync();
The 'cleanContactList' method loops through a DataGridView's rows, during which I try something like this:
int percentComplete = (myRow.Index / contactGridView.Rows .Count ) * 100;
(sender as BackgroundWorker).ReportProgress(percentComplete);
Frustratingly, percentComplete will ALWAYS be zero. If I debug it I can see that there is an actual calculation occurring (e.g. [2000/10000]*100) but the result is always zero.
What am I missing here? If I replace the calculation with, say, a Random.Next(0,100) call it updates fine.

Try index * 100/count. I think you're dividing two ints leading to 0 then multiplying by 100.
For example, this:
int index = 50;
int count = 100;
int percent = index/count * 100;
int percent2 = index * 100/count;
Console.WriteLine("{0} & {1}", percent, percent2);
Outputs 0 & 50.

[2000/10000]*100) but the result is always zero
C# 101 for beginners. Actually more programming - it is the same in most languages that know variable types.
Operations happen on the alrgest most precice variable type involved.
2000 (integer) / 10000 (integer) is aninteger result rounded = 0
I suggest you FIRST multiply, THEN divide. Or choose a different variable type either in the variables, or in the formula (i.e. [(float)2000 will convert the whole formulat to use floats.

Related

How to increase value of an integer higher than 1 in one command?

You could write example++; multiple times in your loop if you need to increase by more than 1, but what if i need to increase by like 100? Is there a way to make it multiply or increase by more than 1? (other than multiplying it in Console.WriteLine)
Per the comment from peter:
example += 100;
Means the same as
example = example + 100;
This is called Compound Assignment and there are many operators that do their work in this way, such as
example -= 100;
example *= 100;
For the full list, refer to the MSDN linked above
Any assignment in c# returns the assigned value so it can be used as part of a bigger statement. The += is no different, and this will print "x incremented is 101":
int x = 1;
Console.WriteLine("x incremented is " + (x+= 100));
The only thing worthy of note is that ++ exists in two forms, either x++ or ++x - the first form returns the value of x before it was incremented, the second form returns the value after.
int x = 1;
Console.WriteLine("x incremented is " + (x++)); //x is now 2 but the message says it is 1
Console.WriteLine("x incremented is " + (++x)); //x is now 3 and the message says it is 3
+= only returns the value after increment. There is no form that returns x before you add 100 to it
The simplest solution to increase value of example by an amount x would be example=example+x. This is more legible, however you can use the short form example+=x.

C# How do basic operation time vary with the size of the numbers?

Context of this is a function, which needs to run pretty much once per frame, and is therefore very critical performance-wise. This function contains a loop, and operations inside it.
private int MyFunction(int number)
{
// Code
for (int i = 0; i <= 10000; i++)
{
var value = i * number
var valuePow2 = value * value;
// Some code which uses valuePow2 several times
}
return 0; // Not actual line
}
Now, because of mathematical properties, we know that (a * b)² is equal to a² * b²
So, it would be possible to make my function into this:
private int MyFunction(int number)
{
// Code
var numberPow2 = number * number;
for (int i = 0; i <= 10000; i++)
{
var iPow2 = i * i
var valuePow2 = numberPow2 * iPow2;
// Some code which uses valuePow2 several times
}
return 0; // Not actual line
}
intuitively, this seems like it should be faster, since number² does not vary, and is now only calculated once outside of the loop. At the very least, this would be much faster for a human to do, because the x² operation is done on a much smaller number during the loop.
What I am wondering, is in C#, when you use types like int, will the multiplication actually be faster with smaller numbers?
For example, will 5 * 5 execute faster than 5000 * 5000?
If so, then the second version is better, even if by a small margin, because of that.
But if, for a given data type, the time is constant, then the first version of the function is better, because half of the calculations will be done on smaller numbers, because I do the same amount of multiplication in the loop both times, but in the second version I do one extra multiplication before the start.
I am aware that for all intent and purposes, the performance difference is negligible. I was suggested the second version in a Code Review because the function is critical, and I can't find any documentation to support either view.
For example, will 5 * 5 execute faster than 5000 * 5000?
For compile-time constants, 5 * x is cheaper than 5000 * x because the former can be done with lea eax, [rdi + rdi*4].
But for runtime variables, the only integer instruction with data-dependent performance is division. This applies on any mainstream CPU: pipelining is so important that even if some cases could run with lower latency, they typically don't because that makes scheduling harder. (You can't have the same execution unit produce 2 results in the same cycle; instead the CPU just wants to know that putting inputs in on one cycle will definitely result in the answer coming out 3 cycles later.)
(For FP, again only division and sqrt have data-dependent performance on normal CPUs.)
Code using integers or FP that has any data-dependent branching can be much slower if the branches go a different way. (e.g. branch prediction is "trained" on one sequence of jumps for a binary search; searching with another key will be slower because it will mispredict at least once.)
And for the record, suggestions to use Math.Pow instead of integer * are insane. Simply converting an integer to double and back is slower than multiplying by itself with integer multiply.
Adam's answer links a benchmark that's looping over a big array, with auto-vectorization possible. SSE / AVX2 only has 32-bit integer multiply.
And 64-bit takes more memory bandwidth. That's also why it shows speedups for 16 and 8-bit integers. So it finds c=a*b running at half speed on a Haswell CPU, but that does not apply to your loop case.
In scalar code, imul r64, r64 has identical performance to imul r32, r32 on Intel mainstream CPUs (since at least Nehalem), and on Ryzen (https://agner.org/optimize/). Both 1 uop, 3 cycle latency, 1/clock throughput.
It's only AMD Bulldozer-family, and AMD Atom and Silvermont, where 64-bit scalar multiply is slower. (Assuming 64-bit mode of course! In 32-bit mode, working with 64-bit integers is slower.)
Optimizing your loop
For a fixed value of number, instead of recalculating i*number, compilers can and will optimize this to inum += number. This is called a strength-reduction optimization, because addition is a "weaker" (slightly cheaper) operation than multiplication.
for(...) {
var value = i * number
var valuePow2 = value * value;
}
can be compiled into asm that does something like
var value = 0;
for(...) {
var valuePow2 = value * value;
...
value += number;
}
You might try writing it by hand that way, in case the compiler isn't doing it for you.
But integer multiplication is very cheap and fully pipelined on modern CPUs, especially. It has slightly higher latency than add, and can run on fewer ports (usually only 1 per clock throughput instead of 4 for add), but you say you're doing significant work with valuePow2. That should let out-of-order execution hide the latency.
If you check the asm and the compiler is using a separate loop counter incrementing by 1, you could also try to hand-hold your compiler into optimizing the loop to use value as the loop counter.
var maxval = number * 10000;
for (var value = 0; i <= maxval; value += number) {
var valuePow2 = value * value;
...
}
Be careful if number*10000 can overflow, if you need it to wrap correctly. In that case this loop would run far fewer iterations. (Unless number is so big that value += number also wraps...)
For a typical processor, multiplying two 32-bit integers will take the same amount of cycles regardless of data in those integers. Most current processors will take nearly twice the time to multiply 64-bit integers as it takes to multiply 32-bit integers.
I did notice a problem in both of your codes. When you multiply two ints, it returns an type int. The var type will set the type to the return value. That means, valuePow2 will be an int.
Since your loop goes up to 10000, if number is 5 or greater, then you will overflow valuePow2.
If you don't want to overflow your int, you could change your code to
private int MyFunction(int number)
{
// Code
for (int i = 0; i <= 10000; i++)
{
long value = i * number; //64bit multiplication
long valuePow2 = value * value; //64bit multiplication
// Some code which uses valuePow2 several times
}
return 0; // Not actual line
}
the modified code should be faster because you may change a 64bit multiplication into a 32bit multiplication
private int MyFunction(int number)
{
// Code
long numberPow2 = number * number; //64bit multiplication
for (int i = 0; i <= 10000; i++)
{
int iPow2 = i * i; //32bit multiplication
long valuePow2 = numberPow2 * iPow2; //64bit multiplication
// Some code which uses valuePow2 several times
}
return 0; // Not actual line
}
But the circuitry in the CPU and the optimization of the compiler can change how many cycles this ends up running.
At the end of the day, you said it best:
I am aware that for all intent and purposes, the performance difference is negligible.

Using the mod operator to decrease value in a textbox

Okay so I have created this vending machine application form and I am having problems getting rid of the change. The machine has 50 10p's in at the start of the day. A fizzy drink costs 40p, so, if the user puts in 50p, he will get change back of 10p. I have a textbox showing the amount of 10p's in the machine, so at the start, 50, after he puts in 50p it will be 55. However, now that he has to get 10p change (I have a release change button), I want the amount of 10p's in the textbox to go to 54...any ideas? I tried using the mod operator but wasn't sure how to use it:
decimal change = decimal.Parse(txtChange.Text)
if (change % 10 > 1)
{
int tenPenny = int.Parse(txt_BoxTenPenny.Text);
int totalTenPen = tenPenny - 1;
txt_BoxTenPenny.Text = totalTenPen.ToString();
}
I know this isn't right, when I was doing research, they were using the % operator and using the number 10 as the numerator..so..I got a bit lost. Any suggestions would be great!
If you're trying to determine how many 10 pennies the user is owed, this is calculated using:
int tenPennies = change / 10
As opposed to the modulus (%) operator, so:
decimal change = decimal.Parse(txtChange.Text)
int tenPenny = int.Parse(txt_BoxTenPenny.Text);
int totalTenPen = tenPenny - change / 10 ;
txt_BoxTenPenny.Text = totalTenPen.ToString();
Hope that helps!
Something like that:
decimal change = decimal.Parse(txtChange.Text)
if (change % 10 > 0)
{
int tenPenny = int.Parse(txt_BoxTenPenny.Text);
int totalTenPen = tenPenny - (change % 10);
txt_BoxTenPenny.Text = totalTenPen.ToString();
}
But is supposed that before that, you have added the 50p the users puts into machine in the txt_BoxTenPenny.
The modulo operator (%) returns the remainder of a division operation. For example, 23 MOD 10 = 3.
In this case I believe you want integer division, or the Floor. That is, you want to divide and throw away the remainder.
Since you are using decimal, I presume change will contain 0.10 for 10p. In that case, try the following:
//calculate the number of 10p coins you will get for change
var tenPenniesChange = (int)Math.Floor(change / 0.10m);
if(tenPenniesChange > 0)
txt_BoxTenPenny.Text = (int.Parse(txt_BoxTenPenny.Text) - tenPenniesChange).ToString();
change -= tenPenniesChange * 0.10;
Note the use of the Math.Floor function. If you had change = 0.13 you will get tenPenniesChange = 1. After the subtraction, you will then get change = 0.03.
This may be of some use:
Issuing vending machine change: Using C# to recursively build and search a tree

Progress bar not updating as expected

The progress bar is going to 70 just fine. It's when I go to update it when the loop starts that the bar doesn't move.
int count = finalFiles.Length; //finalFiles in an array and it varies in size.
int current = 0;
private void uploadWorker_DoWork(object sender, DoWorkEventArgs e)
{
uploadWorker.ReportProgress(20);
DoSomeWork();
uploadWorker.ReportProgress(50);
DoMoreWork();
uploadWorker.ReportProgress(70);
foreach (string file in finalFiles)
{
current++;
doProcess();
uploadWorker.ReportProgress(current / count * 30 + 70);
}
}
Again, the problem is that the progress bar is not updating once it reaches 70. It just doesn't move. The form does not lock up by the way because I'm using background worker.
Does anyone know why that is?
You have an integer current, and an integer count. Since count is bigger, when you do the division it is always 0 (integer division) until current reaches current. You should either make count a double/decimal, or cast one of the two to a double/decimal before doing the division.
I don't know what doProcess() does, but shouldn't you increment current in your foreach?
Looks like you need some parentheses somewhere e.g.
foreach (string file in finalFiles)
{
doProcess();
uploadWorker.ReportProgress( ((current / count) * 30) + 70);
}
OK I don't know that maths you need (sorry, I'm in the middle of something else here), but I would suggest you put parentheses in the calculation, since it looks to me like that could be an issue.

Showing progress value from a list of tasks through ProgressBar

My title may make my question sound confusing, but it is not.
I have a list of tasks to do and a ProgressBar. When I loop through the list of tasks, I want to display the progress through a ProgressBar:
double percentage;
for(int i = 0; i < tasks.Count; i++)
{
percentage = (double)i + 1 / (double)tasks.Count;
this.Invoke((MethodInvoker)delegate
{
progressBar1.Value = (int)Math.Round(percentage * 100);
});
// Do tasks here...
}
So if I have say, 20 tasks I want progressBar1 to have the value of 5 ((1 / 20) * 100), then when it loops through again it has the value of 10, 15 and so on. The method that I am using right now does not work properly, on the first task progressBar1 has a value of 0, then when it loops through again it has the value of 100. Is there a way of doing what I am trying to achieve?
Thanks.
for(int i = 0; i < tasks.Count; i++)
{
double percentage = (double)(i + 1) / (double)tasks.Count;
Action<double> update = p =>
{
progressBar1.Value = (int)Math.Round(p * 100);
};
this.Invoke(update, percentage);
// Do tasks here...
}
Your code should essentially work, however I'd guess your UI just isn't able to update in time (i.e. there's no context switch happening and you return control only once you're done). I don't have that much experience involving C#, multithreading and UI coding, so I might be a bit off here.
What I'd try to do here is sleeping a moment (even essentially 0 seconds should do the trick) once you start doing your tasks within the tasks thread.
A bit off-topic: I'd like to mention that you're overcomplicating it a bit. Just set the maximum value of your progress bar to the number of tasks, then increase it's value 1 by 1, which removes quite a bit of obsolete math within that loop.
Edit: Yeah, just noticed Darin's answer and he's right: You're missing brackets as well, causing your percentage calculation going wrong.
But keep in mind that doing it that way might cause your total percentage to be slightly off due to precision errors (won't matter a lot depending on number of tasks; but you might not be able to hit exactly 100%).

Categories