In a large loop I change several values and need them to be updatet. I dont want to use a BackGroundWorker.
Is there a cheaper way to make the updates, something like to tell the application to paint all pending changes?
void ExampleFunc()
{
// The original function is more complex
for (int i = 0; i < 10000; i++)
{
MyControl1.Text = NewText1(i);
MyControl2.Text = OtherNewText(i);
MyControl1.Update();
MyControl1.Update();
}
}
EDIT:
Why I do need to do it this way:
I usually use BackGroundWorker for situations like that, but in this case on some PCs I get problems with the invokes. So I can't use use it in this case
You say that you cannot use a separate thread and that you must repaint often enough to give the user feedback.
Repainting is expensive. Paint every 10th iteration or every 100ms to reduce the overhead.
Related
I have a property, IList <IMyPlayer> Players {}, which syncs with the game server every time it is summoned. I need to know if it will update every increment when made limiting count in a for loop. The reason why is I'm worried a player may leave the game during this loop.
edit this is a single thread application.
public static IList <IMyPlayer> Players
{
get
{
playersField.Clear(); //GetPlayers() just adds without overwriting so list must be cleared every time.
if (Debugging == false)
{
MyAPIGateway.Multiplayer.Players.GetPlayers (playersField); //everytime the project needs to see all players, this will update. Little heavier on performance but its polymorphic.
}
return playersField.AsReadOnly();
}
}
for (int i = 0; i < AttendanceManager.Players.Count; i++)
{
if (AttendanceManager.Players[i].SteamUserId == MyAPIGateway.Multiplayer.MyId)
{
//do stuff
}
}
I can see several potential problems with your approach:
You add items while you are looping over it, but only loop until the original count is reached. So any added items are not accessed by the for loop
Your getter is doing more than a "normal" getter, which could mean performance problems if clients are not aware of that
using foreach would only call the getter once, which would behave differently that your for loop.
If you want to do this, I would instead make it a GetPlayers() function which makes it clearer that you are creating something as part of the method, and not just getting the current value of a property. If a client wants to reload the list each time they are stil lfree to do so, but it would be more obvious looking at the code.
For example:
for (int i = 0; i < AttendanceManager.GetPlayers().Count; i++)
{
if (AttendanceManager.GetPlayers()[i].SteamUserId == MyAPIGateway.Multiplayer.MyId)
look much more dodgy than a standard property getter.
I would most certainly not do this.
Every time you use your property it is going to call an API. That is going to be terrible for performance. Also it could be quite easy for your property to be called multiple times, even if you don't think it will be. One example I can think of is serialization, or if you are using this as an argument to say an MVC or Web API controller method.
This is what is commonly referred to as a side-effect, which is something you want to avoid in a getter at all costs.
I need a reliable method to check the mouse pointer state, and to count how many times it has changed, e.g. from 'normal' pointer to the hourglass/circle or vice versa. It is part of a performance test that measures response times, and the only way to determine whether a certain business process has finished is by observing the mouse pointer, and to count how many times it has gone from "normal" to "busy" and back again. Once it done this twice, the process is finished. I know - it's horrible, and a rubbish workaround, but it's the only thing I can use.
I have implemented something that works, but it has one crucial weakness: if the mouse pointer changes while the thread has gone to sleep, then I "miss" this change and consequently the exit condition. I will reduce the wait time to 5 or 10 milliseconds, but it's still not a good solution.
Here's the code I have, to give you an idea of what's going on:
TimeSpan timePassed = new TimeSpan();
bool lastMousePointerState = ConvertMousePointerStateToBoolean(Mouse.CursorName);
bool currentMousePointerState = true;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
while(pointerChanges <= 1 && timePassed.Seconds < synchDurationTimeout)
{
Thread.Sleep(100);
currentMousePointerState = ConvertMousePointerStateToBoolean(Mouse.CursorName);
var variableComparison = lastMousePointerState ^ currentMousePointerState;
if (variableComparison.Equals(true))
{
pointerChanges++;
}
timePassed = stopWatch.Elapsed;
lastMousePointerState = currentMousePointerState;
}
I had a look at this article to see if perhaps I could make use of callback functions, and what the article describes does work but only for mouse actions, not its state. Since I have practically no experience with callbacks and making calls out to the OS from .NET, I was hoping someone could tell me if a) what I have in mind is generally possible, and if so b) perhaps provide a working code snippet that would achieve what I need.
Thanks in advance !
Edit: I think the GetCursorInfo function might be what I need, but the description is so terse as to be useless to me ;-)
Despite the overwhelming number of responses here, I'd like to answer my own question :-)
What I ended up implementing (and what is good enough for my purposes) is to use the code that was provided by Atomic Object.
I simply generate the dll from the C++ code, and use a loop to check the state. It is still not as good as a callback/notification mechanism, but I need to finish this and this is the best solution to date.
I have a Windows form program which controls a light. This light has its own class. I can do things like turn it on an off and change the color etc. This I can do without issue. What I want to be able to do, however, is make the light go on for a specific amount of time, i.e. 100 milliseconds or 300 milliseconds (depending on use).
I have tried to used stopwatch to do this, but when I click on the button that is meant to do this, it freezes the program. The light goes on, then doesn't turn off, and I can't use the stop button I have which is meant to turn it off.
The program loads the light, and initialises it, and displays an alert saying it has done this and detected one light. Then I use this:
private void Red_Click_1(object sender, EventArgs e)
{
//Displays Red
System.Threading.Tasks.Task.Factory.StartNew((Action)delegate()
{
displayRedDot();
});
}
This is the displayRedDot()
public void displayRedDot()
{
System.Diagnostics.Stopwatch clock1 = new System.Diagnostics.Stopwatch();
long elapsedTime = clock1.ElapsedMilliseconds;
clock1.Start();
while (elapsedTime < 100)
{
oBlynclightController.Display(BlynclightController.Color.Red);
}
oBlynclightController.Display(BlynclightController.Color.Off);
clock1.Stop();
}
I have some other functions, which are identical this with a different time, which I haven't invoked anywhere yet because I can't get this to work.
Your code will never work since you are blocking the UI thread by busy waiting. This is the reason for your program seems to freeze. Use a timer or async/await instead
async void DisplayRedDot(int duration)
{
oBlynclightController.Display(BlynclightController.Color.Red);
await Task.Delay(duration);
oBlynclightController.Display(BlynclightController.Color.Off);
}
elapsedTime will never change its value. You initialize it right after creating the stopwatch, but never assign a new value to it. Stopwatch.ElapsedMilliseconds is a long. long is a value type. A copy is created and assigned to elapsedTime. You need:
while (clock1.ElapsedMilliseconds < 100)
{
oBlynclightController.Display(BlynclightController.Color.Red);
}
Note that this loop is going to run very quickly until that check returns false. Is this really what you want? I don't know exactly what your code is doing (you don't show us), but why not just set the color to red, wait 100ms, and then set it to... erm, Off.
It's also difficult for humans to pick up a change that only lasts 100ms. It's going to be a flicker at best.
I'm writing a program to help with a game. I need it to update the text box that shows the current exp value, on the forum load it does show the exp, I need it to update the exp like every 3 seconds.
How would I go about doing that?
Here is what I have so far:
Client C = Client.GetClients()[0];
Player P;
P = C.GetPlayer();
expTextBox.Text = ("Experience: " + P.Experience.ToString());
I am not sure if I need a timer (which i have tried and I am very bad at making) or if a backGroundWorker would be best.
Based on your comments, I would recommend that you update your UI when your player/s are attacking, and not use a timer. This will keep your UI the most up-to-date and will probably serve you better than a 3 or 10 second timer. You will have a method like this:
public void Attack(Enemy e)
{
//do your attack code
//did the enemy die?
KillEnemy();
//add exp just for landing a successful attack
AddExp(e);
}
public void AddExp(Enemy e)
{
CurrentPlayer.Exp += e.ExperienceGain;
//update the UI with the new exp
GameWindow.ExperienceBox.Text = CurrentPlayer.Exp;
}
This is of course more pseudocode, because I have no idea what your design looks like, but I've made quite a few games, and this is how I always do it.
Good Luck!
I would encourage you to use Timer if you go to the background worker with infinite loop that is okay but you need to take care of two things when you use background workers:
Updating textbox or any other UI won't work as it needs to be done from the main thread. so you need to check myTextbox.requireInvoke() function before.
Check if the background worker got a cancel signal to exist the infinite loop.
on the other side. you will consume some time when you use timers to update the text box. as the timer would go to the event processing cycle in the windows then fire the event and finally you will write the code in the timer event.
I've been programming console apps for 1 year and I think its time to start something with forms. I don't really know how to make 2 loops work at the same time.
Could any1 help me and give me an example of 2 loops, working together (1 counting from 1 to 100 and 2nd countin from 100 to 200 (both at the same time, lets say 2 message boxes)). I've been looking for smth like that on the net but without success.
I'd also like to know if infinite whiles has to be like while (5>2) or if theres a better way to do that.
Thanks in advance !
I don't really know how to make 2 loops work at the same time.
This is a simple question with an enormous answer, but I'll try to break it down for you.
The problem you're describing at its basic level is "I have two different hunks of code that both interact with the user in some way. I would like to give the user the impression that both hunks of code are running at the same time, smoothly responding to user input."
Obviously the easiest way to do that is to write two programs. That is, make the operating system solve the problem. The operating system somehow manages to have dozens of different processes running "at the same time", all interacting smoothly (we hope) with the user.
But having two processes imposes a high cost. Processes are heavyweight, and it is expensive for the two hunks of code to talk to each other. Suppose you therefore want to have the two hunks of code in the same program. Now what do you do?
One way is to put the two hunks of code each on their own thread within the same process. This seems like a good idea, but it creates a lot of problems of its own. Now you have to worry about thread safety and deadlocks and all of that. And, unfortunately, only one thread is allowed to communicate with the user. Every forms application has a "UI" thread. If you have two "worker" threads running your hunks of code, they have to use cross-thread communication to communicate with the UI thread.
Another way is to break up each hunk of code into tiny little pieces, and then schedule all the pieces to run in order, on the UI thread. The scheduler can give priority to user interaction, and any particular tiny piece of work is not going to block and make the UI thread unresponsive.
It is this last technique that I would suggest you explore. We are doing a lot of work in C# 5 to make it easier to write programs in this style.
See http://msdn.microsoft.com/en-us/async for more information about this new feature.
Not sure if this is what you mean about the two loops.
Infinite loops is anything where while (expression is true) where your expression is 5>2 is always returning true and there is no terminating out of the loop i.e. return; or break;
Drop two labels on the form in Designer view. And then add this in Code view:
public Form1()
{
InitializeComponent();
Shown += new EventHandler(Form1_Shown);
}
void Form1_Shown(object sender, EventArgs e)
{
for (int i = 1; i <= 100; i++)
{
label1.Text = i.ToString();
// "Second loop"
label2.Text = (i + 100).ToString();
Update();
System.Threading.Thread.Sleep(10);
}
}
You'll get two numbers counting simultaneously. One from 1-100. The other from 101-200.
This?
for (int i = 1; i <= 100; i++)
{
//..
for (int i2 = 100; i2 <= 200; i2++)
{
//..
}
}