C# How to terminate a click-event handler with another click-event - c#

I have a click-event handler to a button that forms an ssh connection. I want to terminate this function with another "cancel" button click.
However, when executing an event handler, "cancel" click event handler doesn't run while the first handler executing. I want to override the first handler with "cancel" handler.
private void button_sshconnection_Click(object sender, EventArgs e)
{ /* some code to create ssh connection */ }
private void button_cancel_Click(object sender, EventArgs e)
{ /* some code to terminate button_sshconnection_Click */ }
I tried a code-structure like the above code but as I said second function doesnt run while the first function running. If the structure is wrong, can someone tell me how to do this job.
Thanks in advance,
Onur

You can try implementing async version of your routine, e.g.
private CancellationTokenSource m_Cancellation;
private async void button_sshconnection_Click(object sender, EventArgs e) {
// if method is executing, do nothing. Alternative: cancel and start again
if (m_Cancellation != null)
return;
try {
using (m_Cancellation = new CancellationTokenSource()) {
var token = m_Cancellation.Token;
await Task.Run(() => {
//TODO: implement your logic here, please, note that cancellation is cooperative
// that's why you should check token.IsCancellationRequested
}, token);
}
}
finally {
m_Cancellation = null;
}
}
private void button_cancel_Click(object sender, EventArgs e) {
// If we can cancel, do it
m_Cancellation?.Cancel();
}

Related

How to check if a click event is already in process C# Winforms

I have a method like this:
private async void BtnGivePermit_Click(object sender, EventArgs e)
{
//some code here
}
And I'm trying to add a button to Cancel and in there I wanted to check if any other click event is not in progress. How can I do that in C#?
As Ash suggested, you may want to have a boolean like so:
bool isGivePermitProcessing = false;
private void BtnGivePermit_Click(object sender, EventArgs e)
{
isGivePermitProcessing = true;
try {
...
} finally {
isGivePermitProcessing = false;
}
}
This will give you a definite understanding of whether the function is currently processing or not.
The try-finally block ensures that no exception will cause the isGivePermitProcessing boolean to become indefinitely true.
Extending the above concept into Jimi's suggestion, you could also simply disable the button like so:
private void BtnGivePermit_Click(object sender, EventArgs e)
{
BtnGivePermit.Enabled = false;
try {
...
} finally {
BtnGivePermit.Enabled = true;
}
}
This will also give you a definite understanding of whether the function is currently processing or not while additionally preventing the button from being clicked while already processing a previous click.
If you're intending to make a cancel button for asynchronous operations, you might want to look into the CancellationToken type.

Button click event with two methods which execute one after another by timer

Is it possible to implement in Button click event two executing one after another methods by timer?
Could anyone suggest something?
Sequence as follows:
Within button click
first method execution
some delay (e.g. 3 sec.)
second method execution.
thanks in advance!
Use an async Click event handler with await Task.Delay:
// class member
private TimeSpan clickActionDelay = TimeSpan.FromSeconds(3);
private async void Button_Click(object sender, RoutedEventArgs e)
{
var button = (Button)sender;
button.IsEnabled = false;
firstAction();
// wait 3 seconds without blocking the UI thread
await Task.Delay(clickActionDelay);
secondAction();
button.IsEnabled = true;
}
private void firstAction()
{
...
}
private void secondAction()
{
...
}

How to do not freeze wpf app on closing event

I have a WPF app and I want to execute some method in the Closing event. It can take several minutes, that's why the WPF window freezes. Here is my code:
public MainWindow()
{
InitializeComponent();
this.Closing += MainWindow_Closing;
}
void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
Task.Run(new Action(ClaseAfterThreeSecond)).Wait();
}
void ClaseAfterThreeSecond()
{
Thread.Sleep(3000);
}
I want to do not freeze the WPF app until MainWindow_Closing ends when I click the X button (close button) on the WPF app. Any suggestions?
EDIT:
This way closes the window immediately. I don't need this:
async void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
await Task.Run(new Action(ClaseAfterThreeSecond));
}
You need to make your handler async, but as it async void it returns right after your first await call. Just cancel original closing event and close directly in your code:
private async void Window_Closing(object sender, CancelEventArgs e)
{
// cancel original closing event
e.Cancel = true;
await CloseAfterThreeSeconds();
}
private async Task CloseAfterThreeSeconds()
{
// long-running stuff...
await Task.Delay(3000);
// shutdown application directly
Application.Current.Shutdown();
}

How to pause and resume a backgroundworker thats plotting a chart dynamcally? [duplicate]

Let's say I have a background worker like this:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
while(true)
{
//Kill zombies
}
}
How can I make this background worker start and stop using a button on a WinForm?
Maybe you can use a manualresetevent like this, I didn't debug this but worth a shot. If it works you won't be having the thread spin its wheels while it's waiting
ManualResetEvent run = new ManualResetEvent(true);
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
while(run.WaitOne())
{
//Kill zombies
}
}
private void War()
{
run.Set();
}
private void Peace()
{
run.Reset();
}
Use the CancelAsync method.
backgroundworker1.CancelAsync();
In your loop inside the worker thread.
if (backgroundWorker.CancellationPending) return;
This doesn't happen immediately.
This is how to do it (link to answer below)
By stop do you really mean stop or do you mean pause?
If you mean stop, then this is a piece of cake. Create a button click event handler for the button you want to be responsible for starting the background worker and a button click event handler for the one responsible for stopping it. On your start button, make a call to the background worker method that fires the do_work event. Something like this:
private void startButton_Click(System.Object sender,
System.EventArgs e)
{
// Start the asynchronous operation.
backgroundWorker1.RunWorkerAsync();
}
On your stop button, make a call to the method that sets the background worker's CancellationPending to true, like this:
private void cancelAsyncButton_Click(System.Object sender,
System.EventArgs e)
{
// Cancel the asynchronous operation.
this.backgroundWorker1.CancelAsync();
}
Now don't forget to check for the CancelationPending flag inside your background worker's doWork. Something like this:
private void KillZombies(BackgroundWorker worker, DoWorkEventArgs e)
{
while (true)
{
if (worker.CancellationPending)
{
e.Cancel = true;
}
}
}
And your doWork method:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
KillZombies(worker, e);
}
I hope this can steer you in the right direction. Some further readings:
http://msdn.microsoft.com/en-us/library/b2zk6580(v=VS.90).aspx
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
http://msdn.microsoft.com/en-us/library/waw3xexc.aspx
I haven't tested this, I have code somewhere that I'll have to see exactly what I did, but something like this is an adaptation of Fredrik's answer:
private bool _performKilling;
private object _lockObject = new object();
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
while(true)
{
if (_performKilling)
{
//Kill zombies
}
else
{ //We pause until we are woken up so as not to consume cycles
Monitor.Wait(_lockObject);
}
}
}
private void StartKilling()
{
_performKilling = true;
Monitor.Pulse(_lockObject);
}
private void StopAllThatKilling()
{
_performKilling = false;
]
More complete example of this pattern here:
https://github.com/AaronLS/CellularAutomataAsNeuralNetwork/blob/fe9e6b950e5e28d2c99350cb8ff3157720555e14/CellLifeGame1/Modeling.cs

method waiting for an winform event

in a programm i've been developing, a method is needed to wait until ENTER is clicked inside a specific textbox (generally, winform event called). i know i shold be doing this with threads, but dont know how to make a method that will do that. more specificly, i don't know how to call the event method on the thread, and cannot call in on Main, because it's blocked until this method is called.
the method stopping the Main thread is:
void WaitForInput()
{
while (!gotInput)
{
System.Threading.Thread.Sleep(1);
}
}
thanks for helpers.
Just subscribe to KeyDown (or KeyPress) event of your textbox:
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
// do your stuff
}
}
You can start by changing the WaitForInput method to be threaded by using Tasks like this:
private void WaitForInput()
{
Task.Factory.StartNew(() =>
{
while (!gotInput)
{
System.Threading.Thread.Sleep(1);
}
MessageBox.Show("Test");
});
}
Then catch the KeyPressed event of the textbox and change the state of the boolean gotInput to true like this:
private void KeyDown(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)13)
gotInput = true;
}
Good luck
Use the async/await keywords from .NET 4.5. You could do something like this:
CancellationTokenSource tokenSource; // member variable in your Form
// Initialize and wait for input on Form.Load.
async void Form_Load(object sender, EventArgs e)
{
tokenSource = new CancellationTokenSource();
await WaitForInput(tokenSource.Token);
// ENTER was pressed!
}
// Our TextBox has input, cancel the wait if ENTER was pressed.
void TextBox_KeyDown(object sender, KeyEventArgs e)
{
// Wait for ENTER to be pressed.
if(e.KeyCode != Keys.Enter) return;
if(tokenSource != null)
tokenSource.Cancel();
}
// This method will wait for input asynchronously.
static async Task WaitForInput(CancellationToken token)
{
await Task.Delay(-1, token); // wait indefinitely
}
currently i'm stuck with a dinosaur computer that has XP on it (.NET 2008 and cannot upgrade until april or so). i've ended up following a solution from the comments, and makethe main thread wait and run the entries on threads.
thanks!

Categories