Improving threading CPU usage in C# - c#

I am using SharpDX to make a GUI interface and associated code to allow control of the mouse cursor/emulate key presses but even at idle my app uses 15%+ cpu to the point where it increases my CPU temp +10C while my app is running, here is controller update loop running in its own thread:
private void CallToChildThread()
{
Program.stateOld = controller.GetState();
while (controller.IsConnected)
{
Program.stateNew = controller.GetState();
CheckButtons();
Point cursor;
GetCursorPos(out cursor);
short tx;
short ty;
tx = Program.stateNew.Gamepad.LeftThumbX;
ty = Program.stateNew.Gamepad.LeftThumbY;
float x = cursor.X + _xRest;
float y = cursor.Y + _yRest;
float dx = 0;
float dy = 0;
// Handle dead zone
float lengthsq = tx * tx + ty * ty;
if (lengthsq > DEAD_ZONE * DEAD_ZONE)
{
float mult = speed * getMult(lengthsq, DEAD_ZONE, acceleration_factor);
dx = getDelta(tx) * mult;
dy = getDelta(ty) * mult;
}
x += dx;
_xRest = x - (int)x;
y -= dy;
_yRest = y - (int)y;
SetCursorPos((int)x, (int)y);
Program.stateOld = Program.stateNew;
}
}
CheckButtons is just a function i use to check which buttons have been pressed, I've tried running this inside the controller update thread but I cannot get the buttons to perform as expected.
the while() and GetCursorPos contribute the most towards the total cpu usage. I've tried to compare packet numbers so my app is idle when the controller isn't being used but that causes major issues with handling cursor position(it's very slow and intermittent)
Edit: I've set the thread to background and its priority to BelowNormal but that didn't improve CPU usage very much

This is a tight loop, so it's going to fully use a CPU core. Just add a Thread.Sleep(10) at the end of each iteration. Adjust the delay if it's not responsive enough, but with 10 ms it'll be polling the controller state 100 times per second, which is already a lot.
private void CallToChildThread()
{
Program.stateOld = controller.GetState();
while (controller.IsConnected)
{
// Your update logic
Thread.Sleep(10); // Adjust the delay as needed
}
}
Also, note that lowering the thread priority is not going to decrease CPU usage. It just tells your thread to yield to another if there's not enough CPU available for everybody, which obviously isn't the case.

Related

Movement is dependent to frame-rate. How can i make it independent from frame-rate

i am pretty new to coding. till now i searched lots of things yet i still couldn't solve my problem. I am trying to make a gameObject follow a line/graph. i tried to give him a negative-Y velocity and adding small numbers(something like; update{mybody.velocity += 0.005}) each update to make it move. but i encountered a problem which is at low frame-rate my object is taking a super wide path and at higher frame-rate it take super tight path. how can i make my movement independent.
private float curve = 0;
private float curvemax = 2.3f;
[SerializeField]
private float curveupdate = 0.05f;
if (tracking.found && !hareketeBaşlandı)
{
curve = -(curvemax);
triggered1 = true;
hareketeBaşlandı = true;
print(curve);
}
if (transform.position.y != y1-curvemax && tracking.found)
{
curve += curveupdate;
print(curve+"Curving");
}
if (curve >= (curvemax))
{
curve = 0;
y2 = transform.position.y;
transform.position = new Vector3(transform.position.x, y1, transform.position.z);
tracking.found = false;
tracking.shouldsearch = false;
StartCoroutine("trackCD");
print("track off");
myBody.velocity = new Vector2(myBody.velocity.x, curve);
hareketeBaşlandı = false;
}
Note that using DateTime.Now and TimeSpan calculations as in this answer are quite expensive ... especially if you use it every frame just to calculate a delta in seconds.
This is actually exactly what Unity already provides in Time.deltaTime the time in seconds passed since last few was rendered .. so why calculate it complicated if we already know the value ;)
curve += curveupdate * Time.deltaTime;
In simple words multiplication by Time.deltaTime converts any value from "value per frame" into a frame-rate independent "value per second"
Instead of thinking about "rate of change," you must think about "rate of change per unit of time".
For example, you seem to be updating curve based on curveupdate = 0.05f;, which has a rate of change of 0.05f. You need to be thinking about how much rate of change per second. Assuming you currently get 0.05f change per frame, and let's say 10 frames per second, that means your rate of change per second is 0.5f (ten times higher) per second.
You then apply this amount multiplied by the number of seconds elapsed. Here's how to do it.
First when you kick off the animation, you need to remember when it started:
var lastUpdateTime = DateTime.Now;
Then change this:
curve += curveupdate;
To this:
DateTime currentTime = DateTime.Now;
float secondsElapsed = (float)(currentTime - lastUpdateTime).TotalMilliseconds / 1000F;
curve += (curveupdate * secondsElaped);
lastUpdateTime = currentTime;
This way, the amount of change scales depending on how much time has passed. If no time has passed, it will scale all the way down to 0, and if hours have passed, it will end up very very large. To an end user, the rate of change should seem consistent over time as a result.

Smooth, Fast Coroutines?

So I have a bunch of Coroutines running/working fine in my game.
However, one of them is for a power meter, and here's the issue...
You press the button, the power meter uses the coroutine to start filling up the power meter. (represented by the width of a red panel)
The goal is to make the meter fill up fast enough, as to where you can't just get "full power" every time. However, it also has to be smooth, and look nice.
The problem I'm facing is that my coroutine is maxed out on speed, and can't go any faster, and the meter is moving too slowly. So to "speed up" the meter, I have to use larger width increasing increments on the red panel.
It works, but, this causes 2 problems.
It doesn't look smooth. (It looks choppy and jittery)
It misses a whole bunch of values/possibilities. (e.g. The bar has to increase by a unit of "50" to make it fast enough to be difficult. But that's dumb, because that makes only 12 possibilities when stopping the meter. And there could be up to 600!)
Has anyone faced this before? If so, what's the best approach to making a fast, but smooth power meter, that can still hit a full range of value possibilities?
Thanks,
Ben
Here is my Code:
public static IEnumerator StartPitchMeter(Player.Guy guy, float duration)
{
var dur = 0.01f;
do
{
yield return new WaitForSeconds(dur);
PlayerControls.PitchMeter += 50f;
if (PlayerControls.PitchMeter > 600) PlayerControls.PitchMeter = 0f;
PlayerControls.pitchMeter.sizeDelta = new Vector2(PlayerControls.PitchMeter, 50);
} while (!PlayerControls.stopPitch);
}
If you're using a coroutine to update something for graphical purposes, you want to update on every available render frame (same as how often Update methods are called). So, instead of waiting for a set amount of time to pass, use yield return null and then move the meter according to Time.deltaTime, the time elapsed since the last frame in seconds. In this case, you can multiply Time.deltaTime by how many units per second you would like the meter to fill:
public static IEnumerator StartPitchMeter(Player.Guy guy, float duration)
{
do
{
yield return null;
// Fill 50 units per second.
float fillThisFrame = Time.deltaTime * 50f;
PlayerControls.PitchMeter += fillThisFrame;
if (PlayerControls.PitchMeter > 600) PlayerControls.PitchMeter = 0f;
PlayerControls.pitchMeter.sizeDelta = new Vector2(PlayerControls.PitchMeter, 50);
// Not sure what the 50 is doing here so it might be this instead:
// PlayerControls.pitchMeter.sizeDelta = new Vector2(PlayerControls.PitchMeter, fillThisFrame);
} while (!PlayerControls.stopPitch);
}

Refreshing image at constant frame rate using Observable.Interval is slower than it should

Update:
I isolated the problem to its core components and a much shorter minimal working example in another question:
Observable.Interval not updating UI with expected frequency
I need to display a sequence of images (which are read from a folder) as a "movie", at a constant, previously known, frame-rate.
I have an Image control in WPF, whose Source is data-bound to a ViewModel property Image. I then proceed to update that image on a timely basis, using an Observable.Interval event source. For each elapsed interval, the UpdateImage is called, which updates the image inside a Task.Run() call.
My problem is: when I experimentally increase effective frame-rate (which depends on actual frame-rate and also on playback speed), the playback keeps being at normal speed up tu a given value. Above that value, it starts to look slower.
I believe that it has to do with RaisePropertyChanged call, but I'm not sure. I tried using SubscribeOnDispatcher (or whas it ObserveOnDispatcher?) but anyway it didnt have an effect.
Questions are:
- What I am doing wrong?
- How could I investigate and resolve the problem?
UPDATE:
It's worth mentioning that the getter for Image calls CreateImageForIndex(), which is a method that could have a non-trivial cost. Would it be possible to "async" it?
ViewModel (partial):
CancellationTokenSource _cancelPlay;
double _speed;
public void Play(double speed)
{
_speed = speed;
_cancelPlay = new CancellationTokenSource();
Observable.Interval(TimeSpan.FromSeconds(1.0 / (Math.Abs(speed) * Exame.Model.Configurações.FrameRate)))
.Subscribe(t => ExecuteRun(), _cancelPlay.Token);
}
public void Stop()
{
_cancelPlay?.Cancel();
}
void ExecuteRun()
{
Task.Run(() =>
{
Index = Math.Max(0, Math.Min(_model.MaxIndex, Index + 1 * Math.Sign(_speed)));
});
}
public int Index
{
get { return _model.Index; }
set
{
_model.Index = value;
RaisePropertyChanged(null); // this tells view to get a new value for `Image` too!
}
}
public ImageSource Image => _model.CreateImageForIndex(Index);
I've followed a hint from #Enigmativity (in the other answer I posted), that in Windows the resolution of timers is 15ms at most.
So I tested another strategy: spinning a while loop with an "when elapsed" condition, similar to a game loop, measuring time with a Stopwatch, and everything is working fine now.
public void Play(double speed)
{
_speed = speed;
_cancelPlay?.Cancel();
_cancelPlay = new CancellationTokenSource();
Task.Run(() => PlayLoop(_cancelPlay.Token), _cancelPlay.Token);
}
void PlayLoop(CancellationToken token)
{
var sw = Stopwatch.StartNew();
double previous = sw.ElapsedMilliseconds;
double timeInterval = 1000.0 / (Math.Abs(_speed) * _exame.Model.Configurações.FrameRate);
while (!token.IsCancellationRequested)
{
var current = sw.ElapsedMilliseconds;
var elapsed = current - previous;
if (elapsed > timeInterval)
{
Índice = Math.Max(0, Math.Min(ÍndiceMáximo, Índice + 1 * Math.Sign(_speed)));
previous = current;
}
}
}

Create a parabolic trajectory with fixed angle

I'm trying to throw an arrow in my XNA game, but I'm having a hard time trying to realize a good parabola.
What I need:
The more you hold Enter stronger the arrow goes.
The arrow angle will be always the same, 45 degrees.
This is what I have already have:
private float velocityHeld = 1f;
protected override void Update(GameTime gameTime)
{
if (Keyboard.GetState().IsKeyDown(Keys.Enter) && !released)
{
timeHeld += velocityHeld;
holding = true;
}
else
{
if (holding)
{
released = true;
holding = false;
lastTimeHeld = timeHeld;
}
}
if (released && timeHeld > 0)
{
float alpha = MathHelper.ToRadians(45f);
double vy = timeHeld * Math.Sin(alpha);
double vx = timeHeld * Math.Cos(alpha);
ShadowPosition.Y -= (int)vy;
ShadowPosition.X += (int)vx;
timeHeld -= velocityHeld;
}
else
{
released = false;
}
}
My question is, what do I need to do to make the arrow to go bottom as it loses velocity (timeHeld) to make a perfect parabola?
The solutions discussed above rely on you calculating a new velocity on every iteration, and then calculating the delta (change) from the previous position to determine the current position.
This fits in with the normal logic of a game loop. It is however computationally more complex than it needs to be, and is possibly unstable due to rounding errors.
The simpler and more stable solution is to determine the equation for the parabola and use this to directly work out the position at time t after launch.
Let the arrow start at x=0, y=0. Let the launch velocity be v. At time t after launch the a coordinate of the arrow is x = kt, where k = v*cos(45) = v/sqrt(2).
The y position is a quadratic, y = at^2 + bt + c where we don't know a, b, c.
But when t=0, y=0 so c=0
When t=0, the initial downward velocity is v*sin(45) = v/sqrt(2)
Using a tiny bit of calculus (differentiating position to get velocity), at t=0
v/sqrt(2) = 2at + b = b
Differentiating velocity to get acceleration, we get the initial acceleration at t=0 is 2a. But the only acceleration is due to gravity, so 2a=-g where g is your gravitational constant.
Putting these two equations together, at time t
x(t) = v/sqrt(2);
y(t) = -(g/2)t^2 + vt/sqrt(2)
You know v and t, you define g, so you can work out the x and y co-ordinates at time t directly from this equation.
This is a more straightforward approach and more robust (rounding errors will not accumulate). It is how I personally do it. My hand grenades always follow perfect parabolic arcs, and do so in a computationally efficient manner.
Note: I never heard of XNA until now, but I do use C#. Let me know if this doesn't quite work, though the gist of it should be there.
In your last if-statement, after Enter key is released, you want to increase the downward velocity by a certain (small constant) amount every time you call Update (I assume increasing the y-coordinate makes things move "down" on screen). To do this, as soon as Enter is released, instead of calling double vy = timeHeld * Math.Sin(alpha) every time, save the result into a variable you can reference later, then use a bool value to keep track of when to calculate that value, which is ONLY right after Enter is released.
In other words, it goes something like this:
// extra variables
bool justReleased = false;
double vy, vx;
...
protected override void Update(GameTime gameTime)
{
// ...
if (holding)
{
released = true;
holding = false;
lastTimeHeld = timeHeld;
justReleased = true; // add this here
}
// ...
if (released && timeHeld > 0)
{
float alpha = MathHelper.ToRadians(45f);
// not local variables anymore. Also I flipped the sign - my intention is that initial vertical velocity is "upwards"
if(justReleased)
{
vy = -1 * timeHeld * Math.Sin(alpha);
vx = timeHeld * Math.Cos(alpha);
justReleased = false;
}
ShadowPosition.Y += (int)vy; // Note: I flipped this operator
ShadowPosition.X += (int)vx;
timeHeld -= velocityHeld;
// increase the downward velocity
vy += 2; // or some constant. I can't test this. :\
}
else
{
released = false;
}
}
Hopefully this works, though there might be more efficient ways to do this. Though this isn't a physics site, see this for reference ;-)

How can I make the progress bar update fast enough?

I'm using a progress bar to show the user how far along the process is. It has 17 steps, and it can take anywhere from ~5 seconds to two or three minutes depending on the weather (well, database)
I had no problem with this in XP, the progress bar went fine, but when testing it in vista I found that it is no longer the case.
For example: if it takes closer to 5 seconds, it might make it a 1/3 of the way through before disappearing because it's completed. Even though it's progress is at 17 of 17, it doesn't show it. I believe this is because of the animation Vista imposes on progress bars and the animation cannot finish fast enough.
Does anyone know how I can correct this?
Here is the code:
This is the part that updates the progress bar, waiting is the form that has the progress bar.
int progress = 1;
//1 Cash Receipt Items
waiting.setProgress(progress, 18, progress, "Cash Receipt Items");
tblCashReceiptsApplyToTableAdapter1.Fill(rentalEaseDataSet1.tblCashReceiptsApplyTo);
progress++;
//2 Cash Receipts
waiting.setProgress(progress, "Cash Receipts");
tblCashReceiptsTableAdapter1.Fill(rentalEaseDataSet1.tblCashReceipts);
progress++;
//3 Checkbook Codes
waiting.setProgress(progress, "Checkbook Codes");
tblCheckbookCodeTableAdapter1.Fill(rentalEaseDataSet1.tblCheckbookCode);
progress++;
//4 Checkbook Entries
waiting.setProgress(progress, "Checkbook Entries");
tblCheckbookEntryTableAdapter1.Fill(rentalEaseDataSet1.tblCheckbookEntry);
progress++;
//5 Checkbooks
waiting.setProgress(progress, "Checkbooks");
tblCheckbookTableAdapter1.Fill(rentalEaseDataSet1.tblCheckbook);
progress++;
//6 Companies
waiting.setProgress(progress, "Companies");
tblCompanyTableAdapter1.Fill(rentalEaseDataSet1.tblCompany);
progress++;
//7 Expenses
waiting.setProgress(progress, "Expenses");
tblExpenseTableAdapter1.Fill(rentalEaseDataSet1.tblExpense);
progress++;
//8 Incomes
waiting.setProgress(progress, "Incomes");
tblIncomeTableAdapter1.Fill(rentalEaseDataSet1.tblIncome);
progress++;
//9 Properties
waiting.setProgress(progress, "Properties");
tblPropertyTableAdapter1.Fill(rentalEaseDataSet1.tblProperty);
progress++;
//10 Rental Units
waiting.setProgress(progress, "Rental Units");
tblRentalUnitTableAdapter1.Fill(rentalEaseDataSet1.tblRentalUnit);
progress++;
//11 Tenant Status Values
waiting.setProgress(progress, "Tenant Status Values");
tblTenantStatusTableAdapter1.Fill(rentalEaseDataSet1.tblTenantStatus);
progress++;
//12 Tenants
waiting.setProgress(progress, "Tenants");
tblTenantTableAdapter1.Fill(rentalEaseDataSet1.tblTenant);
progress++;
//13 Tenant Transaction Codes
waiting.setProgress(progress, "Tenant Transaction Codes");
tblTenantTransCodeTableAdapter1.Fill(rentalEaseDataSet1.tblTenantTransCode);
progress++;
//14 Transactions
waiting.setProgress(progress, "Transactions");
tblTransactionTableAdapter1.Fill(rentalEaseDataSet1.tblTransaction);
progress++;
//15 Vendors
waiting.setProgress(progress, "Vendors");
tblVendorTableAdapter1.Fill(rentalEaseDataSet1.tblVendor);
progress++;
//16 Work Order Categories
waiting.setProgress(progress, "Work Order Categories");
tblWorkOrderCategoryTableAdapter1.Fill(rentalEaseDataSet1.tblWorkOrderCategory);
progress++;
//17 Work Orders
waiting.setProgress(progress, "Work Orders");
tblWorkOrderTableAdapter1.Fill(rentalEaseDataSet1.tblWorkOrder);
progress++;
//18 Stored procs
waiting.setProgress(progress, "Stored Procedures");
getAllCheckbookBalancesTableAdapter1.Fill(rentalEaseDataSet1.GetAllCheckbookBalances);
getAllTenantBalancesTableAdapter1.Fill(rentalEaseDataSet1.GetAllTenantBalances);
//getCheckbookBalanceTableAdapter1;
//getTenantBalanceTableAdapter1;
getTenantStatusID_CurrentTableAdapter1.Fill(rentalEaseDataSet1.GetTenantStatusID_Current);
getTenantStatusID_FutureTableAdapter1.Fill(rentalEaseDataSet1.GetTenantStatusID_Future);
getTenantStatusID_PastTableAdapter1.Fill(rentalEaseDataSet1.GetTenantStatusID_Past);
selectVacantRentalUnitsByIDTableAdapter1.Fill(rentalEaseDataSet1.SelectVacantRentalUnitsByID);
getRentBasedBalancesTableAdapter1.Fill(rentalEaseDataSet1.GetRentBasedBalances);
getAgingBalanceTableAdapter2.Fill(rentalEaseDataSet1.GetAgingBalance);
waiting.Close();
Here is the waiting form:
public partial class PleaseWaitDialog : Form {
public PleaseWaitDialog() {
CheckForIllegalCrossThreadCalls = false;
InitializeComponent();
}
public void setProgress(int current, int max, int min, string loadItem) {
Debug.Assert(min <= max, "Minimum is bigger than the maximum!");
Debug.Assert(current >= min, "The current progress is less than the minimum progress!");
Debug.Assert(current <= max, "The progress is greater than the maximum progress!");
prgLoad.Minimum = min;
prgLoad.Maximum = max;
prgLoad.Value = current;
lblLoadItem.Text = loadItem;
}
public void setProgress(int current, string loadItem) {
this.setProgress(current, prgLoad.Maximum, prgLoad.Minimum, loadItem);
}
}
Vista introduced an animation effect when updating the progress bar - it tries to smoothly scroll from the previous position to the newly-set position, which creates a nasty time lag in the update of the control. The lag is most noticeable when you jump a progress bar in large increments, say from 25% to 50% in one jump.
As another poster pointed out, you can disable the Vista theme for the progress bar and it will then mimic the behavior of XP progress bars.
I have found another workaround: if you set the progress bar backwards, it will immediately paint to this location. So, if you want to jump from 25% to 50%, you would use the (admittedly hackish) logic:
progressbar.Value = 50;
progressbar.Value = 49;
progressbar.Value = 50;
I know, I know - it's a silly hack - but it does work!
The reason for this whole mess is the interpolating animation effect introduced by Vista and W7. It has aboslutely nothing to do with thread blocking issues. Calling setProgress() or setting the Value property driectly, triggers an animation effect to occur, which I will explain how to cheat:
I came up with a hack of setting the maximum according to a fixed value. The maximum property does not trigger the effect, thus you get to freely move the progress around with instant response.
Remember that the actual shown progress is given by: ProgressBar.Value / ProgressBar.Maximum. With this in mind, the example below will move the progress from 0 to 100, repensented by i:
ProgressBar works like this:
progress = value / maximum
therefore:
maximum = value / progress
I added some scaling factors needed, should be self explanatory:
progressBar1.Maximum *= 100;
progressBar1.Value = progressBar1.Maximum / 100;
for (int i = 1; i < 100; i++)
{
progressBar1.Maximum = (int)((double)progressBar1.Value / (double)(i + 1) * 100);
Thread.Sleep(20);
}
It sounds like you're doing everything on the UI thread and thus not releasing the message pump. Have you tried using smoething like BackgroundWorker and the ProgressChanged event? See MSDN for an example.
BackgroundWorker is ideal for loading external data - but note that you shouldn't do any data-binding etc until you get back to the UI thread (or just use Invoke/BeginInvoke to push work to the UI thread).
Try invoking the call to the waiting.setProgess() method since waiting seems to live in another thread and this would be a classic cross thread call (which the compiler warns you about if you let him).
Since Control.Invoke is a bit clumsy to use I usually use an extension method that allows me to pass a lambda expression:
waiting.ThreadSafeInvoke(() => waiting.setProgress(...));
.
// also see http://stackoverflow.com/questions/788828/invoke-from-different-thread
public static class ControlExtension
{
public static void ThreadSafeInvoke(this Control control, MethodInvoker method)
{
if (control != null)
{
if (control.InvokeRequired)
{
control.Invoke(method);
}
else
{
method.Invoke();
}
}
}
}
I use Mark Lansdown's excellent answer as an Extension method for the ProgressBar control.
public static void ValueFast(this ProgressBar progressBar, int value)
{
progressBar.Value = value;
if (value > 0) // prevent ArgumentException error on value = 0
{
progressBar.Value = value - 1;
progressBar.Value = value;
}
}
Or you can also do it this way which only sets the ProgressBar value property twice instead of three times:
public static void ValueFast(this ProgressBar progressBar, int value)
{
if (value < 100) // prevent ArgumentException error on value = 100
{
progressBar.Value = value + 1; // set the value +1
}
progressBar.Value = value; // set the actual value
}
Simply call it on any ProgressBar control using the extension method:
this.progressBar.ValueFast(50);
If you really wanted to you could also check the current Windows Environment and only do the hack section of code for Windows Vista+ since Windows XP's ProgressBar does not have the slow progress animation.
Expanding on the answer given by Silas Hansen, this one seems to give me perfect results every time.
protected void UpdateProgressBar(ProgressBar prb, Int64 value, Int64 max)
{
if (max < 1)
max = 1;
if (value > max)
value = max;
Int32 finalmax = 1;
Int32 finalvalue = 0;
if (value > 0)
{
if (max > 0x8000)
{
// to avoid overflow when max*max exceeds Int32.MaxValue.
// 0x8000 is a safe value a bit below the actual square root of Int32.MaxValue
Int64 progressDivideValue = 1;
while ((max / progressDivideValue) > 0x8000)
progressDivideValue *= 0x10;
finalmax = (Int32)(max / progressDivideValue);
finalvalue = (Int32)(value / progressDivideValue);
}
else
{
// Upscale values to increase precision, since this is all integer division
// Again, this can never exceed 0x8000.
Int64 progressMultiplyValue = 1;
while ((max * progressMultiplyValue) < 0x800)
progressMultiplyValue *= 0x10;
finalmax = (Int32)(max * progressMultiplyValue);
finalvalue = (Int32)(value * progressMultiplyValue);
}
}
if (finalvalue <= 0)
{
prb.Maximum = (Int32)Math.Min(Int32.MaxValue, max);
prb.Value = 0;
}
else
{
// hacky mess, but it works...
// Will pretty much empty the bar for a split second, but this is normally never visible.
prb.Maximum = finalmax * finalmax;
// Makes sure the value will DEcrease in the last operation, to ensure the animation is skipped.
prb.Value = Math.Min(prb.Maximum, (finalmax + 1));
// Sets the final values.
prb.Maximum = (finalmax * finalmax) / finalvalue;
prb.Value = finalmax;
}
}
First. I'd never turn off the CheckForIllegalCrossThreadCalls option.
Second. Add a Refresh() after you update the progress. Just because you're doing work in a different thread doesn't mean your GUI thread is going to get around to updating.
I have the same problem.
I have a form with multiple progress bars (top one is for example file x/n, bottom one is task y/m)
The top progress bar does not update TIMELY while the bottom one does
Programatically I update it, invalidate, explicit process message, refresh or sleep does not fix it. Funny thing is that bottom progress bar and other component (time elapsed text) updates fine.
This is purely a Vista+theme problem (animations like previously suggested, XP or Vista with classic theme works fine.
When displaying a message box after the top progress bar has travelled to 100 (programmatically, not visually) I first see the message box and then I see the progress completing
I found that SetWindowTheme(ProgressBar.Handle, ' ', ' '); as explained on
Disabling progress bar animation on Vista Aero
works (but I have old style progress bars now)
Did you try Application.DoEvents(); ?

Categories