C# Wpf Opacity Not Returning To 0 - c#

so im attempting to make a simple function to fade in and out a UIElement
the issue that is occuring is the element fades in fine and has an opacity of 1 but on the fade out the opacity finishes at arround 0.01 oppose to 0.
public static async Task<bool> FadeIO(UIElement target, int FadeTime = 100, int DelayBeforeFade = 5000, int DelayBeforeOutFade = 10000)
{
double OpacTick = 0; //The "counter" for the while loops.
double FadeAmount = ((double)1 / FadeTime); //Calculates the required opacity increment for the fade to happen in the specified time.
await Task.Delay(DelayBeforeFade); //Holds until the required delay before the fade has been reached.
do
{
target.Opacity = 0 + OpacTick; //Alters the target's opacity based on the current loop cylce.
OpacTick += FadeAmount; //Alters the counter by the pre calculated alteration amount.
await Task.Delay(1); //Halts the loop
} while (OpacTick <= 1); //Loops finished when the target's opacity is 1.
OpacTick = 0; //Resets the loop counter.
await Task.Delay(DelayBeforeOutFade); //Holds until the required delay before the fade out has been reached
do
{
target.Opacity = 1 - OpacTick; //Alters the target's opacity based on the current loop cylce.
OpacTick += FadeAmount; //Alters the counter by the pre calculated alteration amount.
await Task.Delay(1); //Halts the loop
} while (OpacTick <= 1); //Loops finished when the target's opacity is 0 and the counter is therefor 1.
return true;
}
The strangest thing about the issue is that when tested on different systems the opacity can fully return to 0 while on some systems it end at arround 0.01

That last loop iteration doesn't get you to 0:
You set the opacity to ~0.01, then increment OpacTick, which is then checked against 1. It never actually sets the opacity to the incremented amount.
That being said, this is totally unnecessary. A DoubleAnimationUsingKeyFrames would serve you far better.

Related

C# Unity Engine, how to limit UI Slider

i need to limit UI Slider.
Now i want the Slider to Stop, if the Limit is 0, but being able to slide back and decrease their value.
like:
Min = 0;
Max = 20;
Limit = Max-SliderValues;
SliderValues = Slider1.value+Slider2.value+Slider3.value+slider4.value;
Slider1.value = 10;
Slider2.value = 2;
Slider3.value = 2;
Slider4.value = max 6;
Can this be done with Unity?
Example:
One slider can reach max and if so, no slider can be moved until the maxed slider has been decreased. I'll give an example:
Workers in Sum: 100;
Assigned workers: Mining+Fishing+Crafting+Gym;
Workers available : 100-Assigned workers;
You have 4 Sliders: Mining, Fishing, Crafting, Gym
Each slider decreases Worker Available and increases Assigned Workers.
The theoretical maximum is 100, practical Workers available.
The Sliders need to stop when WA = 0, but the Problem is, with the decreasing Value, the Slider stops at half and all Sliders will jump back to 0 if you try to push them further as the value allows.
It's very simple, just use:
Slider1.minValue = desiredMinValue;
or
Slider1.maxValue = desiredMaxValue;
Here's the documentation for UI sliders if you have anymore issues with them: https://docs.unity3d.com/2018.3/Documentation/ScriptReference/UI.Slider.html

Unity: flash at frequency with variable on/off ratio

I want to be able to flash stuff at a certain frequency. For an example, let's say 2Hz. I also want to be able to specify a ratio, where I can have the thing displayed for let's say 2/3 of the cycle and have it hidden for 1/3, so the ratio would be 2:1. It's a wild bunch of flashing, so I Need to stay flexible in the way I do it. There might be some flashing with a ratio of 3:5 and a frequency of 2Hz, and some other flashing at 4Hz with ratio 1:1, and so on.
Also, I need to be able to flash in sync. So if one object is flashing already and I start flashing another one, they need to be in sync (or rather their cycles need to be in sync, the flashing may vary as the ratio may be different). But if at the same frequency, they need to "turn on" at the same time, even if their ratios are different. Also, they all need to turn on at the same time the slowest turns on.
My current approach: I have a GameObject FlashCycle, that essentially in it's update method calculates a progress for the 3 frequency's I have (2Hz, 4Hz and 8Hz).
float time = Time.time;
twoHerzProgress = (time % twoHerzInSeconds) / twoHerzInSeconds;
fourHerzProgress = (time % fourHerzInSeconds) / fourHerzInSeconds;
eightHerzProgress = (time % eightHerzInSeconds) / eightHerzInSeconds;
I have tried different times, but that didn't really matter so let's just stick to that one if you don't think it's a bad idea!
Now, whenever I want to flash an object, in it's own Update() I do this:
switch (flashRate.herz)
{
case FlashRateInterval.twoHerz:
show = flashCycle.oneHerzProgress <= onTimePercentage;
case FlashRateInterval.fourHerz:
show =flashCycle.twoHerzProgress <= onTimePercentage;
case FlashRateInterval.eightHerz:
show =flashCycle.fourHerzProgress <= onTimePercentage;
default:
show =true;
}
and then just continue and have the object displayed if show == true.
Unfortunately this doesn't flash the objects at a nice smooth and regular interval. I measured the 2Hz interval and got differences in the ratio of up to 48ms, and though it seems like not much it really makes a difference on the screen.
So the question boils down to: How can I get quick, reqular flashes while maintaining the flexibility (ratio and frequency wise) and have a syncronized flash?
Thanks for your help!
You could use Coroutines and WaitForSeconds to achieve that
// onRatio and offRatio are "optional" parameters
// If not provided, they will simply have their default value 1
IEnumerator Flash(float frequency ,float onRatio = 1, float offRatio = 1)
{
float cycleDuration = 1.0f / frequency;
float onDuration = (onRatio/ (onRatio + offRatio)) * cycleDuration;
float offDuration = (offRatio/ (onRatio + offRatio)) * cycleDuration;
while(true)
{
show = true;
yield return new WatForSeconds(onDuration);
show = false;
yield return new WatForSeconds(offDuration);
}
}
so you can call it either with a frequency e.g. 8Hz
StartCoroutine(Flash(8.0f));
this is actually equal to any call where you set onRatio = offRatio e.g.
StartCoroutine(Flash(8.0f, onRatio = 1, offRatio = 1));
StartCoroutine(Flash(8.0f, onRatio = 2, offRatio = 2));
....
or with a frequency and ratios e.g. 1(on):2(off) with 8Hz
StartCoroutine(Flash(8.0f, onRatio = 1, offRatio = 2));
With this setup the Coroutine runs "forever" in the while(true)-loop. So, don't forget before you start a new Coroutine with different parameters to first stop all routines with
StopAllCoroutines();
Now if you want to change that dynamically in an Update method, you would have to add some controll flags and additional variables in roder to make sure a new Coroutine is only called when something changed:
FlashRateInterval currentInterval;
float currentOnRatio = -1;
float currentOffRatio = -1;
void Update()
{
// if nothing changed do nothing
if(flashRate.herz == currentInterval
//todo && Mathf.Approximately(<yourOnRatio>, currentOnRatio)
//todo && Mathf.Approximately(<yourOffRatio>, currentOffRatio)
) return;
StopAllCoroutines();
currentInterval = flashRate.herz;
//todo currentOnRatio = <yourOnRatio>;
//todo currentOffRatio = <yourOffRatio>;
switch (flashRate.herz)
{
case FlashRateInterval.twoHerz:
StartCoroutine(2.0f);
//todo StartCoroutine(2.0f, onRatio = <yournRatio>, offRatio = <yourOffRatio>);
case FlashRateInterval.fourHerz:
StartCoroutine(4.0f);
//todo StartCoroutine(4.0f, onRatio = <yournRatio>, offRatio = <yourOffRatio>);
case FlashRateInterval.eightHerz:
StartCoroutine(8.0f);
//todo StartCoroutine(8.0f, onRatio = <yournRatio>, offRatio = <yourOffRatio>);
default:
show =true;
}
}
Notes:
I dont know your FlashRateInterval but if you need to use it for some reason you could make it like
public enum FlashRateInterval
{
AllwaysOn,
twoHerz = 2,
fourHerz = 4,
eightHerz = 8
}
in order to directly use the correct values.
I would call a frequency variable flashRate.herz. You also wouldn't call a size value cube.meters. I'ld recommend to rename it to flashRate.frequency.
To archieve that syncing you would somehow need access to all Behaviours and compare their values (so I'ld say some static List<YourBehavior>) and than e.g. in the Coroutine wait until all bools are e.g. set to true before continuing with your own one. For that you would need an additional bool since it is possible that show is true permanently on one component.
public bool isBlinking;
IEnumerator Flash(float frequency ,float onRatio = 1, float offRatio = 1)
{
//todo: You'll have to set this false when not blinking -> in Update
isBlinking = true;
float cycleDuration = 1.0f / frequency;
float onDuration = (onRatio/ (onRatio + offRatio)) * cycleDuration;
float offDuration = (offRatio/ (onRatio + offRatio)) * cycleDuration;
// SYNC AT START
show = false;
// wait until all show get false
foreach(var component in FindObjectsOfType<YOUR_COMPONENT>())
{
// skip checking this component
if(component == this) continue;
// if the component is not running a coroutine skip
if(!component.isBlinking) continue;
// Now wait until show gets false
while(component.show)
{
// WaitUntilEndOfFrame makes it possible
// for us to check the value again already before
// the next frame
yield return new WaitForEndOfFrame;
}
}
// => this line is reached when all show are false
// Now lets just do the same but this time wating for true
// wait until all show get false
foreach(var component in FindObjectsOfType<YOUR_COMPONENT>())
{
// skip checking this component
if(component == this) continue;
// if the component is not running a coroutine skip
if(!component.isBlinking) continue;
// Now wait until show gets false
while(!component.show)
{
// WaitUntilEndOfFrame makes it possible
// for us to check the value again already before
// the next frame
yield return new WaitForEndOfFrame;
}
}
// this line is reached when all show are getting true again => begin of loop
while(true)
{
.........
Instead of using FindObjectsOfType<YOUR_COMPONENT>() which is kind of slow you could also do something like
public static List<YOUR_COMPONENT> Components = new List<YOUR_COMPONENT>();
private void Awake()
{
if(!Components.Contains(this)){
Components.Add(this);
}
}
so you also get currently disabled components and objects
You got some diferences because you are doing everything in an Update() cycle with <= condition. On slower/faster machines you will have more/less differences because the frame's duration will never be equal to your frequency.
Try doing everything in a Corotine: unity coroutine docs
//bad code below but i think its more understandable like this
IEnumerator Flash()
{
while(true)
{
BlinkOn();
Sync();//sync here another cicle if you want to sync when on starts
yield return new WaitForSeconds(yourDuration);// yourDuration*multiplier/something+0.5f....ecc
BlinkOff()
Sync();//sync here another cicle if you want to sync when of starts
yield return new WaitForSeconds(yourDuration);
}
}

Why doesn't my program wait like I need it to?

Ok pretty much what I am trying to do is have my program wait a predetermined amount of times then move the character to another spot on the grid (which is notated by the "panel_x" and "panel_y" variables). Instead it waits and then moves the character around every frame...Im not sure what I am doing wrong. I believe I need a coroutine, but I may be wrong.
//How I am calling the coroutine
void Update()
{
if(HP != 0)
{
StartCoroutine(Wait());
}
}
//The Coroutine I need to run to move my character
//around...I need this to run until the character's
//hp reaches 0.
IEnumerator Wait()
{
while(true)
{
//I need it to wait...
yield return new WaitForSeconds(3);
//Then move the character to another
//grid...
panel_x = Random.Range(1, 4);
panel_y = Random.Range(1, 4);
}
}
Update runs on every frame. What's happening here is that you're calling Wait() on every frame which will run multiple instances in an infinite loop.
I believe what you're trying to do is change the x and y values every 3 seconds.
If so, try something like this.
float timer = 0.0f;
void Update()
{
if (HP != 0)
{
timer += Time.deltaTime;
if (timer >= 3)
{
panel_x = Random.Range(1, 4);
panel_y = Random.Range(1, 4);
timer = 0;
}
}
}
Time.deltaTime returns the time passed between frames so it can be used as a timer by summing it every frame. When 3 seconds has passed, we reset the timer to 0 and run our method.
Did you modify that HP ever after? If HP is not 0, then the StartCoroutine(Wait()) will be called every time Update() is executed. That is why you get the weird result.
Your function doesn't seem to take any parameters, so I can provide you other method like Invoke as an alternative.
Invoke(x, y) executes a function after a certain amount of seconds delay. In your case for example:
void Update(){
if(HP != 0)
Invoke("MoveChar", 3); //execute MoveChar() after 3 seconds
}
MoveChar(){
panel_x = Random.Range(1,4);
panel_y = Random.Range(1,4);
}
Just for your info, there is also InvokeRepeating(x, y, z) which maybe you won't need in this case.
It repeats every z seconds after function x being called with y delay.
void Start(){
//execute MoveChar() after 3 seconds and call the
//function again after 0.5 seconds repeatedly
InvokeRepeating("MoveChar", 3, 0.5);
}
MoveChar(){
panel_x = Random.Range(1,4);
panel_y = Random.Range(1,4);
}

How to animate a simple shape moving vertically?

So, I have a rectangle "rectangle1", at 160,160.
I want it to move smoothly to cordinates 160,30, with a duration of about 1 second. (time delay)
I've figured out that some basic code to move the shape is
rectangle1.Location = new Point(160,30);
However, when I tried doing a for loop with
rectangle1.Location = new Point(160, rectangle1.Location.Y - 100);
it just moved there instantly. Which I should have expected really. Same occurred with
int count = 0;
while(count != 300)
{
rectangle1.Location = new Point(160, rectangle1.Location.Y -1);
count += 2;
}
So, I assume I need some sort of clock / timer loop, that moves it by x pixels every x milliseconds. Not sure how to do this, so help would be appreciated.
Also, I'm going to be animating two other rectangles horizontally, which will then move up at the same time/speed as rectangle1. I think I'll have to "delay" rectangle1's movement until they are in position, correct?
Thanks.
PS: I've googled a fair bit, but since I'm not entirely sure what I'm looking for, it wasn't very fruitful.
If you need smooth movements, it's great to use timers, threads, backgroundworkers.
Here is what you need to do. Assuming you have the code that increment/decrement x,y points for the shape.
Steps:
set timer interval to for e.g. 100
set an integer int count=0; *
in timer_tick event do the moving work
private void timer1_Tick(object sender, EventArgs e)
// no need to use your while loop anymore :))
{
If(count< 300) //set to your own criteria
{
//e.g. myrect.location=new point(x,y);
// rectangle1.Location = new Point(160, rectangle1.Location.Y -1);
}
count += 2;
}

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