Ok hi, I am making a program in Microsoft Visual Studio and every time I run it and and click start (I have a start button), it will do what I have it programmed to do, but the form always freezes and doesn't display what i want it too (it says "Not Responding" once i start it). It is good for doing it job, but I have things on the form that are supposed to be shown. While it keeps freezing, it does not give me the option to stop it, or show any labels I have set to change, during it's running. Any help on this will be appreciated. Thank You.
EDIT: This is what I have:
void CheckAll()
{
for (; ; )
{
CheckPixel();
Application.DoEvents();
}
}
It is constantly doing CheckPixel();, I take it that is the reason why it is freezing. There are never any breaks.
This usually means you are blocking the UI thread (e.g. running a long operation inside a button click handler). Instead of using the UI thread, you will generally need to offload long I/O operations to the ThreadPool or your own worker threads. This is not always easy to do and requires careful design and a good understanding of concurrency, etc.
Your application is freezing because it's in an infinite loop. I don't know how you can fix it, because I don't know exactly what you're trying to do here.
Update: since I need to go to bed, I'm going to toss out a total guess here. Your CheckPixel() method should probably have a signature like this:
public bool CheckPixel(int x, int y)
{
Color color = _myBitmap.GetPixel(x, y);
return (color == Color.Red);
}
where _myBitmap is a form-scoped Bitmap. Then your CheckAll() method should be something like this:
public bool CheckAll()
{
for (int x = 0; x < _myBitmap.Width; x++)
{
for (int y = 0; y < _myBitmap.Height; y++)
{
if (CheckPixel(x, y))
{
return true;
}
}
}
return false;
}
G'night folks! I'll be here all week.
Put your program in a try-catch block and then have any exception thrown print in a messagebox.
http://msdn.microsoft.com/en-us/library/0yd65esw%28VS.80%29.aspx
Also, try inserting a breakpoint at the point of click to identify where exactly it freezes up.
Instead of Application.DoEvents() why don't you replace with Threading.Thread.Sleep(0)? I'm not an expert but I prefer Thread.Sleep better then DoEvents.
You need to have some way of exiting out of the loop.
Either your for loop needs the logic to go from ? to ? (as in
for(int i = 0; , < 100; 1++)
which will will loop 100 times
OR
for(;;)
{
if(SomeCondition == true)
{
break;
}
}
Related
I'm modifying existing C# code in order to pilote a piston. Every 30ms, I have a direct feedback of the position of this piston, through an event. The value is stored in a global variable I use to get the current position of the piston.
What I'm trying to achieve: for a given distance input (A->C), I want the piston to travel at full speed for 95% of the distance (A->B), and then slower for the remaining 5% (B->C).
I have access to a command that defines the speed and the destination of the piston : pos(velocity, destination).
However, if I write that code:
pos(fullSpeed,B);
pos(reducedSpeed, C);
the piston directly goes from fullSpeed to reducedSpeed
I tried to use a while loop to compare the current position of the piston with the goal destination, however, upon entering the while loop, the variable storing the piston position does not update anymore.
However, I noticed that by throwing a MessageBox in between, the position value keeps on getting updated, and I can simply click "ok" to launch the second command.
pos(fullSpeed,B);
MessageBox.show("Wait");
pos(reducedSpeed, C);
I would like to know why the "while" loop stops the update of the position variable but the MessageBox does not. I mean, as long as I don't click the "ok" button, the box is here preventing me from doing anything, which for me ressembles a while loop behaviour. Is there another way for me to do this instead of the MessageBox ?
I have little to no knowledge when it comes to C# and no support. I have tried to look in the documentation, but I did not find an answer (I have probably missed it). Any lead is more than welcome.
EDIT: I have no documentation for that code, and it is barely commented. Here is what I gathered (really hope it helps):
To move the piston, taht function is called:
MyEdc.Move.Pos(control, speed, destination, ref MyTan);
control simply define what we pilote (a distance or a load, it is an enum), and I have no idea what MyTan does. Only thing I know is that the MyEdc.Move.Pos returns an error code.
If I look at the definition of "pos", I am redirected to class
public DoPEmove Move;
containing among other things:
public DoPE.ERR Pos(DoPE.CTRL MoveCtrl, double Speed, double Destination, ref short Tan);
DoPE.ERR is also an type enum. However, I cannot reach the definition of a function named "Pos". Coud it be within the .dll included ?
The following is the code that allows me to access the position of the piston (without the global variables):
private int OnData(ref DoPE.OnData Data, object Parameter)
{
if (Data.DoPError == DoPE.ERR.NOERROR)
{
DoPE.Data Sample = Data.Data;
Int32 Time = Environment.TickCount;
if ((Time - LastTime) >= 300 /*ms*/)
{
LastTime = Time;
string text;
text = String.Format("{0}", Sample.Time.ToString("0.000"));
guiTime.Text = text;
text = String.Format("{0}", Sample.Sensor[(int)DoPE.SENSOR.SENSOR_S].ToString("0.000"));
guiPosition.Text = text;
text = String.Format("{0}", Sample.Sensor[(int)DoPE.SENSOR.SENSOR_F].ToString("0.000"));
guiLoad.Text = text;
text = String.Format("{0}", Sample.Sensor[(int)DoPE.SENSOR.SENSOR_E].ToString("0.000"));
guiExtension.Text = text;
}
}
return 0;
}
Which is called using
MyEdc.Eh.OnDataHdlr += new DoPE.OnDataHdlr(OnData);
I realise how little I know on how the soft operates, and how frustrating this is for you. If you think this is a lost cause, no problem, I'll try Timothy Jannace solution, and if it does not help me, I'll stick with the MessageBox solution. I just wanted to know why the MessageBox allowed me to sort of achieve my objectif, but the while loop did not, and how to use it in my advantage here.
I tried to use a while loop to compare the current position of the
piston with the goal destination, however, upon entering the while
loop, the variable storing the piston position does not update
anymore.
While you are in the while loop, your app can no longer receive and process the feedback event.
One possible solution would be to use async/await like this:
private const int fullSpeed = 1;
private const int reducedSpeed = 2;
private int currentPistonPositon = 0; // global var updated by event as you described
private async void button1_Click(object sender, EventArgs e)
{
int B = 50;
int C = 75;
pos(fullSpeed, B);
await Task.Run(() =>
{ // pick one below?
// assumes that "B" and "currentPistonPosition" can actually be EXACTLY the same value
while (currentPistonPositon != B)
{
System.Threading.Thread.Sleep(25);
}
// if this isn't the case, then perhaps when it reaches a certain threshold distance?
while (Math.Abs(currentPistonPositon - B) > 0.10)
{
System.Threading.Thread.Sleep(25);
}
});
pos(reducedSpeed, C);
}
Note the button1_Click method signature has been marked with async. The code will wait for the while loop inside the task to complete while still processing event messages because of the await. Only then will it move on to the second pos() call.
Thank you for your answer ! It works like a charm ! (good catch on the
EXACT value). I learnt a lot, and I am sure the async/await combo is
going to be very usefull in the future ! – MaximeS
If that worked well, then you might want to consider refactoring the code and making your own "goto position" method like this:
private void button1_Click(object sender, EventArgs e)
{
int B = 50;
int C = 75;
GotoPosition(fullSpeed, B);
GotoPosition(reducedSpeed, C);
}
private async void GotoPosition(int speed, int position)
{
pos(speed, position);
await Task.Run(() =>
{
while (Math.Abs(currentPistonPositon - position) > 0.10)
{
System.Threading.Thread.Sleep(25);
}
});
}
Readability would be greatly improved.
You could even get fancier and introduce a timeout concept into the while loop. Now your code could do something like below:
private void button1_Click(object sender, EventArgs e)
{
int B = 50;
int C = 75;
if (GotoPosition(fullSpeed, B, TimeSpan.FromMilliseconds(750)).Result)
{
if (GotoPosition(reducedSpeed, C, TimeSpan.FromMilliseconds(1500)).Result)
{
// ... we successfully went to B at fullSpeed, then to C at reducedSpeed ...
}
else
{
MessageBox.Show("Piston Timed Out");
}
}
else
{
MessageBox.Show("Piston Timed Out");
}
}
private async Task<bool> GotoPosition(int speed, int position, TimeSpan timeOut)
{
pos(speed, position); // call the async API
// wait for the position to be reached, or the timeout to occur
bool success = true; // assume we have succeeded until proven otherwise
DateTime dt = DateTime.Now.Add(timeOut); // set our timeout DateTime in the future
await Task.Run(() =>
{
System.Threading.Thread.Sleep(50); // give the piston a chance to update maybe once before checking?
while (Math.Abs(currentPistonPositon - position) > 0.10) // see if the piston has reached our target position
{
if (DateTime.Now > dt) // did we move past our timeout DateTime?
{
success = false;
break;
}
System.Threading.Thread.Sleep(25); // very small sleep to reduce CPU usage
}
});
return success;
}
If you're using events you are probably having concurrency issues. Especially with events being raised every 30ms!
A very simple way to handle concurrency is to use a lock object to prevent different threads from using contested resources simultaneously:
class MyEventHandler
{
private object _lockObject;
MyEventHandler()
{
_lockObject = new object();
}
public int MyContestedResource { get; }
public void HandleEvent( object sender, MyEvent event )
{
lock ( _lockObject )
{
// do stuff with event here
MyContestedResource++;
}
}
}
Keep in mind that is very simple and by no means perfect in every scenario. If you provide more information about how the events are raised and what you're doing with them people will be able to provide more help.
EDIT:
Using that signature you posted for the Pos method I was able to find documentation on the library you are using: https://www.academia.edu/24938060/Do_PE
The reason you only see the method signature when you goto definition is because the library has been compiled into a dll. Actually, it probably wouldn't be that useful to see the code anyway because it looks like the library is a C# wrapper around native (c or c++) code.
Anyways, I hope the documentation is helpful to you. If you look at page 20 there are some pointers on doing movement. This is going to be a challenge for a new programmer but you can do it. I would suggest you avoid using the event handler to drive your logic and instead stick with using the synchronous versions of commands. Using the synchronous commands your code should operate the same way it reads.
I believe what you'll want to do is add a call to:
Application.DoEvents();
This will allow your application to process posted messages (events), which will allow that global variable to be updated.
I just wanted to know why the MessageBox allowed me to sort of achieve my objectif, but the while loop did not, and how to use it in my advantage here.
The reason that works is because you're giving the WndProc a chance to process events which have been sent to the application. It's not an intended feature of that call to MessageBox.Show();, but it is a consequence. You can do the same thing with a call to Application.DoEvents(); without the interruption of the message box.
I have simple task in my app, but i have problem.
For example:
for (int i = 1; i <= 1000000; i++)
{
if (i % 2 == 0) {
TextBlock.Text += string.Format("{0},", i);
}
}
While app doing that task it takes long time, so I would like it displays number when it is found and not at the end, all numbers together.
What is the simplest way to do that for newbie like me?
It is WP8, C#.
Thanks a lot.
you can keep adding these numbers in a queue object and have a thread looking for a change in the queue object and simultaneously update the textbox.
So the problem is, that UI doesn't get refreshed until your loop end, even if you are appending text to TextBox. The easy way to fix it - is to add Application.DoEvents() call after TextBlock.Text += string.Format("{0},", i);.
But it has some critical downsides (explained here https://stackoverflow.com/a/5183623/2152334).
The right way is to do calculation in a different thread (using Tasks for example) and update UI thread using Dispatcher:
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
TextBlock.Text += ...
});
You can't refresh the display if your code blocks the UI thread. You need to leave the UI thread for your long task.
// We go to a non-UI thread
TaskEx.Run(() => {
for (int i = 1; i <= 1000000; i++)
{
// some long operation here... -_-"
if (i % 2 == 0)
{
// We return to UI thread after long operation to display the result
Deployment.Current.Dispatcher.InvokeAsync(() => {
TextBlock.Text += string.Format("{0},", i);
});
}
}
});
Also you might consider adding a cancellation token to break the loop in case the user leaves the page being displayed.
[edit: this solution is meant for your comment "my app will display few numbers but calculation takes long time". If you really need 1000000 results, try to Dispatcher.InvokeAsync(...) and TextBlock.Text += ... multiple results at a time.]
When the Deactivate event of window W1 is fired I want it to do it's go away & cleanup routine, unless the new foreground window is contained in a list of certain other windows. The other windows are all from the same process but run on different messagepump/GUI-threads. They are all winforms windows.
I created a Deactivate Routine that seems to be doing what I desire, but from the looks of it it feels like something to be ashamed of, so I wanted to ask you for a "cleaner" solution.
Explanation for the code sample posted below:
I lock because I believe I really don't want that monster to run twice at the same time under any circumstances.
I am doing the loop condition for the following reason:
foregroundWindowHandle is sometimes "0" instead of the handle of the window that is actually in foreground, unless I wait a few milliseconds (I tried 100) at the beginning of the Deactivate event. Since I am not sure those 100 ms guarantee me a not 0 foregroundWindowHandle I just wait until I can be sure it's not 0.
GetForegroundWindow() and GetWindowThreadProcessId() are the pInvoked methods of the same name.
Behold, my (working) attempt at solving this:
this.Deactivate += new EventHandler((a, b) =>
{
if (!Monitor.TryEnter(deactivateLockObject))
return;
try
{
while (true)
{
IntPtr foregroundWindowHandle = CSUTIL.GetForegroundWindow();
if (foregroundWindowHandle.ToString() == "0")
{
Thread.Sleep(1);
continue;
}
uint currentForegroundThreadId = CSUTIL.GetWindowThreadProcessId(foregroundWindowHandle, IntPtr.Zero);
if (new uint[] { threadidW1,threadidW2,threadidW3,etc. }.All((currentThreadId) => { return currentThreadId != currentForegroundThreadId; }))
this.MakeInvisible(); // Executes the closing & cleanup routine
break;
}
}
finally
{
Monitor.Exit(deactivateLockObject);
}
});
Ignoring programming style, here are some suggestions.
1) Your event handler may run in the main gui thread or another thread. If run on the gui thread, then "Sleep()" is inappropriate because it will prevent many other gui events from getting a turn. You can force your handler onto the thread pool to avoid this.
2) In the old days, any delay less than 200 ms was likely to prevent other events from being handled. Presumably, the scheduler decided that was not enough time to justify the overhead of saving state switching to a new event, and coming back. It may not be the case now, but I still follow the habit of using 200 ms or more. It may not add anything when the handler is not on the gui thread.
3) Your code as written is only an infinite loop if GetForegroundWindow() forever returns null. In such a case, you have a system error or a corrupt program. You should limit the time spent in the loop, and when exceeding that limit, treat it as a severe or non-recoverable error.
Here is a suggested modification that does these things. Note that in your code, the Deactivate event handler did not return until done, while this example puts the work on a thread and returns right away. The thread task will live at most 60 seconds before being returned to the thread pool.
this.Deactivate += new EventHandler((a, b) => ThreadPool.QueueUserWorkItem((obj) =>
{
if (!Monitor.TryEnter(deactivateLockObject))
return;
try
{
int count = 0;
int interval = 200;
while (count < 60000)
{
IntPtr foregroundWindowHandle = CSUTIL.GetForegroundWindow();
if (foregroundWindowHandle.ToString() != "0")
{
uint currentForegroundThreadId = CSUTIL.GetWindowThreadProcessId(foregroundWindowHandle, IntPtr.Zero);
if (new uint[] { threadidW1,threadidW2,threadidW3,etc. }.All((currentThreadId) => { return currentThreadId != currentForegroundThreadId; }))
{
// do the work on the gui thread
this.Invoke(new Action(this.MakeInvisible)); // Executes the closing & cleanup routine
}
return;
}
count += interval;
Thread.Sleep(interval);
}
this.Invoke(new Action(this.HandleSevereError));
}
finally
{
Monitor.Exit(deactivateLockObject);
}
}));
I have a code that scrolls a growing page to the bottom (until it's not possible to scroll to the bottom).
When it's not possible, it scrolls to the top and the javascript code is finished.
For example: imagine a timeline on facebook.
It's a growing page, so I can scroll it again and again until it's not possible to scroll (then I will be in: "BORN").
So this is my code:
while (i < elements.Count)
{
js.ExecuteScript("var timeId = setInterval( function() {
if(window.scrollY<(document.body.scrollHeight-window.screen.availHeight))
window.scrollTo(0,document.body.scrollHeight); else { clearInterval(timeId);
window.scrollTo(0,0); } },5000);");
i++;
}
I want to add 1 to i only when the setInterval is finished.
I tried the next thing:
while (i < elements.Count)
{
object a = js.ExecuteScript("setInterval( function() {
if(window.scrollY<(document.body.scrollHeight-window.screen.availHeight)) {
window.scrollTo(0,document.body.scrollHeight); return '1'}; else {
clearInterval(timeId); window.scrollTo(0,0); return '2'} },5000);");
while (a != '2') {
// do nothing, this while will be ended when we arrived the bottom and
// go back to the top
}
// all the page is loaded
i++;
}
but it doesn't work.. maybe there is a way to scroll to the bottom more and more and then to the top without using set interval? (but remember: it's a growing page that grows when you scroll it down and down..
How can I do it?
The setInterval function is asynchronous, meaning that it happens after the ExecuteScript function gets a return value, this is why what you tried didn't work. The best solution I can think of is to change a little bit the structure of your code and use C# Threading.
Using C# Threading
This way, what we are going to do is to each time stop the code for 5 seconds and then execute a JavaScript code that checks if you can scroll further down, if yes scroll down and if not scroll back up. This JavaScript code will also return whether we should continue running this loop or not.
Basically, this is the JavaScript code we will execute:
if (window.scrollY < (document.body.scrollHeight - window.screen.availHeight)) {
window.scrollTo(0, document.body.scrollHeight);
return true;
} else {
window.scrollTo(0, 0);
return false;
}
And this is how the overall C# code should look:
while (i < elements.Count)
{
bool run = true;
while (run)
{
System.Threading.Thread.Sleep(5000);
run = (bool)js.ExecuteScript("if(window.scrollY<(document.body.scrollHeight-window.screen.availHeight)){window.scrollTo(0,document.body.scrollHeight);return true;}else{window.scrollTo(0,0);return false;}");
}
i++;
}
find something to use as a variable for when you hit the bottom and then use an if statement in the While loop to increment i when that has happened
Hi Guys i'm trying to let my Screen blink a morse code out using timer , but no luck, can you spot any problem?
Sry but i feel sad for those who cant think out of the box and just mark a -2 without even understanding the situation.
Anyway, found about using await Task.Delay(100) but gridHalfFront.Opacity = 1; isnt being "activated" when its being read. not sure why.
async public void RunMorseCode()
{
foreach (char c in word.ToCharArray())
{
string rslt = Codes[c.ToString()].Trim();
foreach (char c2 in rslt.ToCharArray())
{
if (c2 == '.')
{
gridHalfFront.Opacity = 0;
await Task.Delay(100);
}
else
{
gridHalfFront.Opacity = 0;
await Task.Delay(1000);
}
gridHalfFront.Opacity = 1;
}
}
}
use System.Threading.Thread.Sleep(1000) and/or System.Threading.Thread.Sleep(3000) inside yr loop to make yr screen blink on and off
gridHalfFront.Opacity = 1;
if (c2 == '.')
{
System.Threading.Thread.Sleep(1000);
}
else
{
System.Threading.Thread.Sleep(3000);
}
gridHalfFront.Opacity = 0;
change it to the way it best for you, but dont use those timers
Your code is missing the Timer event handler. After calling Start() and after the elapsed time a Tick event from the Timer will be raised. There you have to change the opacity.
I think you are misunderstanding the use of a Timer. If you put the following code at the top of StartTimer you will see what I mean.
Console.WriteLine("Started {0}", inputTiming);
When you run you will get a bunch of timers are being created immediately. This is not what you want for two reasons. Firstly, they are all assigned to the same variable, so the second is 'logically' killing off the first, etc. Secondly, you don't want them created all at once, as all of the 1 second ones will all run at the same time after 1 second, and all of the 3 second ones will run together after 3 seconds. And, as already mentioned, to run code after the timer expires you need to hook up the event.
BIG EDITS Sorry didn't realise you were looking at Metro. What I have said above still holds, but I will back away from providing a solution.
Given the comments about Sleep() not working on Metro, I think you need to so all the code inside the timer for one character, and then set the interval for the next character from within the timer. Will provide some code in a few minutes...