Using Timer and colour to display morse code - c#

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...

Related

MessageBox and while loop C#

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.

Continue the `while` loop when ExecuteScript(setInterval) is finished

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

How do you check if DateTime is initialized?

I need help with making a code that checks every second if Datetime is started.
If it is started it should close the already running function.
I know dispatchertimer but I want it to run the thread in background.
The reason is because I have a mediaplayer that plays till datetime is started, causing the movie to restart every 1 second.
I would be very thank full if you guys could help me, a little bit desperate...
Dictionary<string, string> listBox3Dict = new Dictionary<string, string>();
private bool listbox3job()
{
AxWMPLib.AxWindowsMediaPlayer axWmp =
wfh.Child as AxWMPLib.AxWindowsMediaPlayer;
DateTime? start = DateTimePicker1.Value;
DateTime? end = DateTimePicker2.Value; // This. End date. If end date. Stop movie.
DateTime now = DateTime.Now;
if (start == null || end == null)
{
}
else if (now >= start.Value && now <= end.Value)
{
foreach (var selected in listBox3.Items)
{
string s = selected.ToString();
if (listBox3Dict.ContainsKey(s))
{
axWmp.URL = (listBox3Dict[s]);
}
}
return true;
}
return false;
}
Alright, against my better judgment, I'm going to provide you a solution that will let you check the value every second. The only reason I'm providing this solution is because the AxWindowsMediaPlayer object does not have an event that is fired as playback occurs. You're going to need to build a BackgroundWorker to do this:
var worker = new BackgroundWorker();
worker.WorkerSupportsCancellation = true;
worker.DoWork += (s, e) =>
{
// here you will check the time
while (end > DateTime.Now)
{
Thread.Sleep(1000);
}
}
and when you're ready to use the BackgroundWorker you'll issue this:
worker.RunWorkerAsync();
however, I'm making some assumptions because you really didn't put enough effort into your question. I'm assuming that you want to check the ending time against DateTime.Now because you declared all of those variables. I've also seen a similar question on here today - performing just about the same operation. The other reason I'm making that assumption is because the control you're using doesn't really provide you a good mechanism to determine the current playback location of the media file.
In the future, please put a lot more effort into your questions. Remember, we know nothing about what you're doing and so it's verify difficult to provide a solution without any context. I know you're probably busy, and you feel like you're under a crunch, but providing us with little to no information isn't going to speed up the process - as you can see from the comments thread.

Have MessageBox appear once (code inside timer)

UPDATE: I've managed to fix my problem. Using the code below, I moved my MessageBox AFTER my XML saving and changed the Timer from 100ms to 400ms. I now have 1 box appear, thank god. Although If anyone has a short cut to updating a single value (ActReminded) in the List array(ActListTask), that'd be great to know.
I'm having a little issue with displaying the MessageBox. Show inside a timer without it spamming me. Here's the part of the code I've been working with:
public class ActiveTasks
{
//Properties here
}
public List<ActiveTasks> ActTaskList = new List<ActiveTasks>();
for (int i = 0; i < ListActive.Items.Count; i++)
{
if (DTime.Date == newDateTime.Date)
{
if (newDateTimeLeft.CompareTo(TimeSpan.Zero) <= 0 && ActTaskList[i].ActReminded != "true")
{
MessageBox.Show("!!!!");
ActTaskList.Add(new ActiveTasks()
{
ActTitle = ActTaskList[i].ActTitle,
ActDesc = ActTaskList[i].ActDesc,
ActDate = ActTaskList[i].ActDate,
ActTime = ActTaskList[i].ActTime,
ActStatus = ActTaskList[i].ActStatus,
ActReminded = "true",
ActRepeat = ActTaskList[i].ActRepeat
});
ListActive.Items.RemoveAt(i);
ActTaskList.RemoveAt(i);
XDocument XmlActTasks = GenerateActiveListToXML(ActTaskList);
}
}
}
I actually decided I may want to hold onto the reminder status, whether it has been shown or not as I wouldn't want a repeated reminder every time the program is opened. Since I don't know of a way to update an individual part of ActTaskList I just re-added it, and then deleted the original. This code manages to recognise that if it happens, it will change the reminder status from false, to true; after I've Ok'ed all the spam. So it will stop the MessageBox once I've managed to closed all the Messageboxes. However, it doesn't stop the spam. Would it be anything to do with the fact I've set the timer to 100ms? Or could their be an alternative way to make the messagebox appear without it being inside the timer?
The odds of the current time lining up exactly to the second what is happening in your loop is small. Why not treat newDateTime as a cut off point and just set a flag?
//Declare this outside of the loop
bool hasDisplayed = false;
//Inside the timer event handler
if (!hasDisplayed && DateTime.Now >= newDateTime)
{
hasDisplayed = true;
MessageBox.Show("!!!!!!!!!!!!!");
}
Can you do something like this?
Action message = () => MessageBox.Show("!!!!!!!!!!!!!"));
object lockOb = new object();
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
lock(lockOb)
if(null != message)
{
message();
message = null;
}
}
You say you've already tried a boolean indicating the message has already been shown, I'm assuming because the code probably looked like it did below.
void TimerLoop()
{
bool msgAlreadyShown;
if(!msgAlreadyShown)
{
MessageBox.Show("!!!!!!!");
}
// Other work in your timer function
}
The problem with that code is that the bool will be set to false each time the function is called by the timer. You haven't posted much code, but you've at least stated what you're trying to accomplish, a timer that checks if a reminder should be presented to the user.
I'm about to make some wild guesses about how you've put together your software, there's a good chance it's way off, but I hope it might point you in the right direction. You could have some sort of reminder class like this:
public class Reminder
{
string Message { get; set;}
DateTime Alarm { get; set; }
bool IsDismissed { get; set; }
}
I'm assuming you might want to have multiple reminders that can be checked for in the timer loop, so your timer loop could look something like:
private List<Reminder> _activeReminders; // A list of reminders
void TimerLoop(object s, ElapsedEventArgs e)
{
lock(_activeReminders)
{
var now = DateTime.Now;
foreach(var reminder in _activeReminders)
{
// only run this code if the time has passed and it hasn't already
// been shown
if(now.CompareTo(reminder.Alarm) >= 0 && !reminder.IsDismissed)
{
MessageBox.Show(reminder.Message);
reminder.IsDismissed = true;
}
}
}
}
This is a pretty naive implementation, since you probably don't want to hold onto the reminders for forever and the reminders are never removed from the _activeReminders list, but you essentially just need to add some sort of state to determine if the reminder has already been shown.
Of course, this isn't a complete example either, since I never new up the _activeReminders field or add anything to it, but I think this might help get the idea of what you need to do across. Also, you might not care about multiple reminders, and your timer code could look nothing like this. The main idea was to show you how you can keep track of the state of a reminder, and tailor it to your own code. The above was just an example.
Also, I haven't actually tested it, so treat it more like pseudocode than anything else. However, the logic is sound, and should it should only cause the message box to appear once.

Program Not Responding

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;
}
}

Categories