How do i fire an event after a few seconds? - c#

I am making a application where i would like to log in with a face detection. But this is not real, its just to make ik look like its scanning.
So when i press the LOG IN button, the kinect takes my picture and show me the picture, on top of it is showing me in a text that its scanning.
Now i am stuck with the following issue, when i press the login button, the scanning label appears, but i would like to fire an other event that takes me to the next page, the homepage.
So i want the SCANNING label appearing for 3 seconds, and then the page should change.
This is what i tried, i worked with a timer, but that doesnt do annything.
private void ActionButton_Click(object sender, System.EventArgs eventArgs)
{
_main.TakePicture();
identifyBox.Source = _main.source.Clone();
scanningLabel.Visibility = Visibility.Visible;
_storyboard = (Storyboard)FindResource("scanningSB");
//_storyboard.Begin();
Start();
}
private void Start()
{
_tm = new Timer(3000);
_tm.Elapsed += new ElapsedEventHandler(_tm_Elapsed);
_tm.Enabled = true;
}
void _tm_Elapsed(object sender, ElapsedEventArgs e)
{
if (_tm == new Timer(3000))
{
((Timer)sender).Enabled = false;
_main.ContentPage.Children.Clear();
_main.ContentPage.Children.Add(_homeScreen);
}
}
Okay i removed the if statement, but now it fires every 3 seconds a method.
How can i make it work 1 time.
Ok even this works, now i my ContentPage wont change? It gives me this error: The calling thread cannot access this object because a different thread owns it.
What can be wrong?

I think you can remove condition
if (_tm == new Timer(3000))
and keep it simple
void _tm_Elapsed(object sender, ElapsedEventArgs e)
{
((Timer)sender).Enabled = false;
_main.ContentPage.Children.Clear();
_main.ContentPage.Children.Add(_homeScreen);
}
when you set _tm = new Timer(3000); it will set the time to fire event after 3 seconds..

Change the _tm_Elapse to this:
void _tm_Elapsed(object sender, ElapsedEventArgs e)
{
if (_tm == (sender as Timer))
{
_main.ContentPage.Children.Clear();
_main.ContentPage.Children.Add(_homeScreen);
}
}
Edit for answering:
"I just want it 1 time to fire after 3 sec"
void _tm_Elapsed(object sender, ElapsedEventArgs e)
{
if (_tm == (sender as Timer))
{
_tm.Stop();
_main.ContentPage.Children.Clear();
_main.ContentPage.Children.Add(_homeScreen);
}
}

This is even simpler, and it will only run once per call, the three second timer is built in, and furthermore, it won't disable other program functionalities while it is running:
async Task Start()
{
await Task.Delay(3000);
_main.ContentPage.Children.Clear();
_main.ContentPage.Children.Add(_homeScreen);
}

Related

Play next file automatically using MediaPlayer Control(AxWindowsMediaPlayer)

When changing AxWindowsMediaPlayer URL in PlayStateChange Event, it doesn't start playing automatically, just changes to "Ready" state.
I have an "AxWindowsMediaPlayer" Control in my C# WinForms program. when I normally change the URL property of WindowsMediaPlayer1, it works fine and plays new mp3 file automatically.
When the song ended WindowsMediaPlayer1 State changes to Stopped and I Want next URL automatically start Playing.
I used PlayStatChange event, so when player state is Stopped, URL Will change, but Not playing automatically!
The player goes to Ready State until I press the play button on the WindowsMediaPlayer1.
Here is the Code:
private void Form1_Load(object sender, EventArgs e)
{
WindowsMediaPlayer1.URL = "6.mp3"; //Works fine
}
private void button1_Click(object sender, EventArgs e)
{
WindowsMediaPlayer1.URL = "4.mp3"; //Works fine. It changes the music.
}
private void WindowsMediaPlayer1_PlayStateChange(object sender,
AxWMPLib._WMPOCXEvents_PlayStateChangeEvent e)
{
if (e.newState == 1) //1 is for "Stopped" State
WindowsMediaPlayer1.URL = "5.mp3";
// Here is the problem.
// URL Will change but player goes to "Ready" State
// But not in "playing" until I press the play button in control.
}
Any help would be appreciated.
As mentioned in media player documentations, you should not set the Url from event handler code. Instead you can play next file this way:
private void axWindowsMediaPlayer1_PlayStateChange(object sender,
AxWMPLib._WMPOCXEvents_PlayStateChangeEvent e)
{
if (e.newState == 1)
{
this.BeginInvoke(new Action(() => {
this.axWindowsMediaPlayer1.URL = #"address of nextfile";
}));
}
}
Also as another option you can consider using a playlist.
I found this note on msdn about player.URL:
"Do not call this method from event handler code. Calling URL from an event handler may yield unexpected results."
so I tried another way to solve it and its worked.
added a timer and a bool varible to check if WindowsMediaPlayer1 is "Stopped"
Here is the solution:
public partial class Form1 : Form
{
bool nextURL = false;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
WindowsMediaPlayer1.URL = "5.mp3";
}
private void WindowsMediaPlayer1_PlayStateChange(object sender, AxWMPLib._WMPOCXEvents_PlayStateChangeEvent e)
{
if (e.newState == 1) // 1 is consider for "Stopped" State
{
nextURL = true; // if the song ended "nextURL" flag sets to true
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (nextURL)
{
WindowsMediaPlayer1.URL = "6.mp3";
nextURL = false;
}
}

how to check whether a button is clicked, inside another button click event in windows form application in C#

well i am having two buttons on a form and I want to start data transfer with the first button and stop on the press of a second button.
code is:
private void stdaq_Click(object sender, EventArgs e)
{
stopped = false;
//while (stopped == false)
if (sender == spdaq)
{
stopped = true;
///break;
Process();
}
else if (sender == stdaq)
{
Process();
}
}
here stdaq is the start button and spdaq is the stop button, the process function is a function which i am implementing and in that with the stopped variable of bool type i am implementing two different functions inside process method, but i want to continually check whether the stop button is pressed or not but here with this code i got no success.
so please help me with how to pass the value true to the stopped variable inside the event click function of start button itself on the press of stop button.
Create cancellation token, start asynchronous Task in button start event handler put your method in this Task, pass reference to this cancellation token and use
it to stop this task in Stop button event handler when you'll need it later.
More information : https://msdn.microsoft.com/en-us/library/jj155759.aspx
Example of how you can use it:
static CancellationTokenSource cts;
static Task t;
private void Method()
{
while (!cts.IsCancellationRequested)
{
// your logic here
}
t = null;
}
private void stdaq_click (object sender, EventArgs e)
{
if(t != null) return;
cts = new CancellationTokenSource();
t = new Task(Method, cts.Token, TaskCreationOptions.None);
t.Start();
}
private void spdaq_Click(object sender, EventArgs e)
{
if(t != null) cts.Cancel();
}
Use two separate Handlers for the start and the stop button. This makes your logic much simpler to follow. Then do soemthing like this:
private void stdaq_Click(object sender, EventArgs e) // Start
{
Process(true);
}
private void spdaq_Click(object sender, EventArgs e) // Stop
{
Process(false);
}
Or even better: Create two seperate Methods StartProcess() and StopProcess().

Breaking from a loop with button click - C#

I have a question regarding looping with button click event, I've tried many methods & searched many pages in search for a simple answer for the past hour, but the truth is each answer just looks like alien code, probably because I'm still very new to developing.
Here's a simplified version of what I'm trying to do :
private string Message = "Hello";
private void Spam(bool loop)
{
if (loop == true)
{
while (loop == true)
{
MessageBox.Show(Message);
}
}
else { MessageBox.Show("Spamming has stopped !! "); }
}
private void button1_Click(object sender, EventArgs e)
{
Spam(true);
}
private void button2_Click(object sender, EventArgs e)
{
Spam(false);
}
Obviously this isn't my API, or it'd be a useless thing to invent, however, the code itself is long & you guys always ask for "relevant code" (No disrespect), so there it is.
My problem : Breaking out of the spam loop upon clicking button 2, the code to me looks decent enough for the API to figure out, but each time button 1 is clicked, the API freezes.
Use a background worker to do your work. You can use the cancellation feature to break out of it when you're done. Your loop as you have it will block the UI thread when executed syncronously, which is why your GUI becomes unresponsive. Note if you do any interaction with the UI in the do work delegate, you need to marshal back onto the UI thread (via invoke for example).
private BackgroundWorker _worker = null;
private void goButton_Click(object sender, EventArgs e)
{
_worker = new BackgroundWorker();
_worker.WorkerSupportsCancellation = true;
_worker.DoWork += new DoWorkEventHandler((state, args) =>
{
do
{
if (_worker.CancellationPending)
break;
Console.WriteLine("Hello, world");
} while (true);
});
_worker.RunWorkerAsync();
goButton.Enabled = false;
stopButton.Enabled = true;
}
private void stopButton_Click(object sender, EventArgs e)
{
stopButton.Enabled = false;
goButton.Enabled = true;
_worker.CancelAsync();
}
Update 2019:
BackgroundWorker is now largely obsolete, replaced by the async/await feature in later versions of C# which is easier to use. Here is an example of how to achieve the same thing using that feature:
private CancellationTokenSource _canceller;
private async void goButton_Click(object sender, EventArgs e)
{
goButton.Enabled = false;
stopButton.Enabled = true;
_canceller = new CancellationTokenSource();
await Task.Run(() =>
{
do
{
Console.WriteLine("Hello, world");
if (_canceller.Token.IsCancellationRequested)
break;
} while (true);
});
_canceller.Dispose();
goButton.Enabled = true;
stopButton.Enabled = false;
}
private void stopButton_Click(object sender, EventArgs e)
{
_canceller.Cancel();
}
There's one important thing to remember:
While your code is being executed, the user cannot interact with your user interface.
That means: You first need to exit the loop (i.e. return from the Spam method), and then the user can click Button2.
That's a hard truth, because it means you cannot write the code in the way you wanted to. Fortunately, there are a few ways to work around that:
Don't use a loop. Use some kind of timer to do the "spamming". Button1 starts the timer, Button2 stops it. What kind of timer is available depends on the user interface library you use (WinForms has a Timer, WPF has a DispatcherTimer).
Do the "spamming" in a background thread. This will allow your user interface to stay responsive, and you can communicate with the background thread, for example, by setting a volatile Boolean. This, however, is an advanced topic (and can quickly lead to complex synchronization issues), so I suggest that you try the other option first.
When you click button1 the Spam method is called and loop is starting. When you click button2 Spam method is called but it's not the same. It's the second execution, so it will check the condition and won't enter into the loop, but the loop in the first call sill will be running.
You should use a flag and the loop should use that flag to determine whether it should be still running. It should look something like that:
bool run = false;
string message = "This API is not original";
private void Spam()
{
while (run == true)
{
MessageBox.Show(message);
}
}
}
private void button1_Click(object sender, EventArgs e)
{
message = "Hellooo";
flag = true;
Spam();
}
private void button2_Click(object sender, EventArgs e)
{
flag = false;
}
Take a look at this concept:
private bool loop = false;
private void Start()
{
loop = true;
Spam("Some Message??");
}
private void Spam(string message)
{
while (loop)
{
MessageBox.Show("This API is not original");
}
}
private void button1_Click(object sender, EventArgs e)
{
loop = true;
}
private void button2_Click(object sender, EventArgs e)
{
loop = false;
}
However, the user won't be able to press a button if a MessageBox keeps popping up as it takes up the main UI thread. In order to prevent this you could use BackgroundWorker or start a new thread.

Stop timer in the middle of the tick

I want to stop a timer but in the middle of the tick, before the tick finishes. But when I use a button to stop the timer, it only stops it after the tick finishes all his functions.
I'm using 4 radiobuttons and a timer that keeps changing the selected radiobutton. When I press the Stop button, my timer stops and I need to know what radiobutton is selected, but the timer just stops after the tick finishes, so the selected radiobutton changes.
The code is:
namespace teste_bola
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Int32 x = 1000;
private void ini_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
}
private void par_Click(object sender, EventArgs e)
{
timer1.Enabled = false;
}
private void t_Click(object sender, EventArgs e)
{
Int32 Intervalo = Convert.ToInt32(tb.Text);
x = Intervalo;
}
private void timer1_Tick(object sender, EventArgs e)
{
r3.Select();
System.Threading.Thread.Sleep(x);
r2.Select();
System.Threading.Thread.Sleep(x);
r1.Select();
System.Threading.Thread.Sleep(x);
r2.Select();
System.Threading.Thread.Sleep(x);
r3.Select();
System.Threading.Thread.Sleep(x);
r4.Select();
System.Threading.Thread.Sleep(x);
}
}
}
You can introduce a flag bool shouldStop , set it when button is clicked, and check it from the Tick handler. If it is true, then just exit the method.
I'm not following what you are trying to accomplish in you code but it seems to me like you are not using the timer correctly.
You should do something like:
On each timer.Tick change the selected radiobox.
What you are actually doing is:
On each timer.Tick change through all radiobox's with a time interval between changes.
This means that on the first timer timeout the tick code is executed.
On the second timer timeout the first tick job was not yet finnished.
This will lead to erratic behaviour to say the least.
My advice. Add the radio buttons to a ArrayList. Then cicle select between each of the ArrayList items on a Timer tick.
try the following
private void timer1_Tick(object sender, EventArgs e)
{
r3.Select();
System.Threading.Thread.Sleep(x);
if(timer1.Enabled == false) return;
r2.Select();
System.Threading.Thread.Sleep(x);
if(timer1.Enabled == false) return;
r1.Select();
System.Threading.Thread.Sleep(x);
if(timer1.Enabled == false) return;
r2.Select();
System.Threading.Thread.Sleep(x);
if(timer1.Enabled == false) return;
r3.Select();
System.Threading.Thread.Sleep(x);
if(timer1.Enabled == false) return;
r4.Select();
System.Threading.Thread.Sleep(x);
}
You can face this behaviour because your thread is sleeping during the execution of the timer1_Tick and thus there might be a queye of events.
As alex proposed you can add a flag, but you should check it after every sleep or, even better, put your animation in the different thread.

Can not click button when a method running

private void AddMyScrollEventHandlers()
{
VScrollBar vScrollBar1 = new VScrollBar();
}
private void button1_Click(object sender, EventArgs e)
{
while (true)
{
if (vScrollBar1.Value + 1 < vScrollBar1.Maximum)
{
vScrollBar1.Value = vScrollBar1.Value + 1;
label1.Text = vScrollBar1.Value.ToString();
}
else
{
break;
}
System.Threading.Thread.Sleep(200);
}
}
private void button2_Click(object sender, EventArgs e)
{
// vScrollBar1.Scroll
}
I am new in C#. I was working on scroll. What I wanted here is, if anyone click button1 then scroll automatically move to the end and I wanted to show gradual value in label1. Also when someone click button2 scrolling stop.
Now the problem is label1 do not show gradual change in value. It shows value once when the scrolling stop.
Also when scrolling continue i,e when while loop is working I can not click on button2. Actually I can not click on the form even.
Someone please give me some idea how to do this.
This happens because the thread that is performing the task is busy, and it's the same thread that updates the UI. You can use a multithreading solution. Take a look at
BackgroundWorker
All the UI events run in the main thread of the application, so the application can only process one event at a time. When the application is processing an event, no other event will be processed.
Since you are doing a UI related work periodically, the best option is to use the Timer class:
Drop Timer from the toolbox into the form.
In the properties window, set the interval to 200.
Double click the timer object to create the Tick event handler.
Put this code in the newly created timer1_Tick method:
if (vScrollBar1.Value + 1 < vScrollBar1.Maximum)
{
vScrollBar1.Value = vScrollBar1.Value + 1;
label1.Text = vScrollBar1.Value.ToString();
}
else
{
timer1.Stop();
}
Change your methods as below:
private void AddMyScrollEventHandlers()
{
timer1.Start();
}
private void button2_Click(object sender, EventArgs e)
{
timer1.Stop();
}
Now you're done.
I would recommend using BackgroundWorker control, as suggested by Agustin Meriles. However, one more important thing to note is that You should use Control.Invoke(...) method to update controls from another thread.
I've modified Your code, tested it in a sample application and it seems to work correctly.
First, add a new BackgroundWorker control to Your form and assign backgroundWorker1_DoWork to its DoWork event.
Then, You can use the code below:
private void button1_Click(object sender, EventArgs e)
{
//code from here is moved to BackgroundWorker control
backgroundWorker1.RunWorkerAsync();
}
private void button2_Click(object sender, EventArgs e)
{
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//while (true)
//the condition directly in the while looks more clear to me
while (vScrollBar1.Value + 1 < vScrollBar1.Maximum)
{
//update controls using Invoke method and anonymous functions
vScrollBar1.Invoke((MethodInvoker)delegate() { vScrollBar1.Value += 1; });
label1.Invoke((MethodInvoker)delegate() { label1.Text = vScrollBar1.Value.ToString(); });
//when called inside BackgroundWorker, this sleeps the background thread,
//so UI should be responsive now
System.Threading.Thread.Sleep(200);
}
}
If You have any problems when using this code, please let me know.
Update
As mentioned in the comments, You could also use ProgressChanged event of the BackgroundWorker. It requires some more changes in the code, but is more suitable in this case. You can find some information about it here: http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.progresschanged.aspx.
If You are not going to add any other code with more processing in the while loop, You can also use Timer control, as suggested by MD.Unicorn in his answer.

Categories

Resources