Insert delay/wait in code c# - c#

public void OpenUpForm(object sender, EventArgs e)
{
if (forms.Count == numberoftimes)
{
forms.ForEach(f =>
{
f.Close();
f.Dispose();
});
forms.Clear();
//Need Delay Here
return;
}
forms.Add(new Form1());
forms.Last().Show();
}
Hello I have this code, I need to add delay after forms.Clear(); But im new to coding i couldnt figure it out.
I have tryed with Task.Delay and Thread.Sleep but it locks my user interface. Is it possible to add a delay that dosent lock the application? Thank you.

You can mark the method async and use this:
await Task.Delay(2000);
will not block the ui thread
public async void OpenUpForm(object sender, EventArgs e)
{
if (forms.Count == numberoftimes)
{
forms.ForEach(f =>
{
f.Close();
f.Dispose();
});
forms.Clear();
await Task.Delay(2000);
return;
}
forms.Add(new Form1());
forms.Last().Show();
}
This will behave like so.
Creates a new task which runs to completion after 2 seconds
Ui Thread is bubbled back up to continue executing/processing other events
Once the 2 seconds is up UI thread returns and resumes executing the async method from after the await

Related

How to close WPF window inside of a Task

I need to run a task to check the connection.
My windows should not be frozen during this check.
So I start the Task, and close my window at the end of this task.
But this returns an exception: InvalidOperationException:'The calling thread cannot access this object because another thread owns it'.
Like this :
private void Window_ContentRendered(object sender, System.EventArgs e)
{
Task.Run(() =>
{
ConnectionState = false;
if (NetworkTools.CheckGlobalConnection() == (ConnectionStatus.NetworkConnectionSuccess, ConnectionStatus.ServerConnectionSuccess))
{
ConnectionState = true;
}
this.Close();
});
}
How do I close my window at the end of the task without freezing it and without having this exception ?
(I have a progress bar that rotates indefinitely)
Or you could just use async await. Task.Run will offload and the await will create a continuation on current SynchronizationContext. In turn giving control back to the UI and closing on the right thread.
private async void Window_ContentRendered(object sender, System.EventArgs e)
{
await Task.Run(() =>
{
ConnectionState = false;
if (NetworkTools.CheckGlobalConnection() == (ConnectionStatus.NetworkConnectionSuccess, ConnectionStatus.ServerConnectionSuccess))
ConnectionState = true;
});
this.Close();
}
Also as noted, Calling ConfigureAwait(false), would not be the right thing to do in this case
Use Dispatcher to queue window closing logic on the unique UI thread.
Something like
Dispatcher.Invoke(
() =>
{
// close window here
});
Whatever is passed into .Invoke(...) as a delegate, is invoked on the UI thread and hence has right to access all UI elements. It is common (and the only correct) way to deal with UI-mutations within non-UI threads.
As an alternate method you can use ContinueWith
private void Window_ContentRendered(object sender, System.EventArgs e)
{
Task.Run(() =>
{
// Your code
}).ContinueWith((tsk) =>
{
this.Close();
}, TaskScheduler.FromCurrentSynchronizationContext());
}

Load form then show a message after defined period of time

I am trying to make a game launcher where there is a limit of 10 minutes the it should close
Problem statement : I want to load the form , user should be able to do activities and then application should close after 10 minute
when i give any kind of sleep or wait in main method, the form itself is not loading i only get the messagebox ,then the application closes.
public MainForm()
{
InitializeComponent();
MessageBox.Show("Welcome");
Task.Run(async () =>
{
await Task.Delay(60000);
}).GetAwaiter().GetResult();
MessageBox.Show("one minute left");
Task.Run(async () =>
{
await Task.Delay(60000);
}).GetAwaiter().GetResult();
MessageBox.Show("time over");
Application.Exit();
}
Use System.Windows.Forms.Timer as follows:
Timer = new System.Windows.Forms.Timer();
Timer.Interval = TIME_IN_MILLISECONDS;
Timer.Tick += Timer_Tick;
private void Timer_Tick(object sender, EventArgs e)
{
//desired behavior
}
System Timer runs async, after selected interval it triggers your method
Use Microsoft's Reactive Framework (NuGet "System.Reactive.Windows.Forms" and add using System.Reactive.Linq;) and then you can do this:
public MainForm()
{
InitializeComponent();
MessageBox.Show("Welcome");
Observable
.Timer(TimeSpan.FromMinutes(1.0))
.ObserveOn(this)
.Subscribe(x => MessageBox.Show("one minute left"));
Observable
.Timer(TimeSpan.FromMinutes(2.0))
.ObserveOn(this)
.Subscribe(x =>
{
MessageBox.Show("time over");
Application.Exit();
});
}
If you want to start a task in a fire and forget fashion there is no need to call GetAwaiter().GetResult(); because this will block the thread. So, basically, there is no point at all of all of these task that you have created. You could simply make use of the Timers. As you are using Windows Forms you can use the System.Windows.Forms.Timer or you can use System.Threading.Timer. I would use the System.Windows.Forms.Timer to implement such a behavior.
Why not just schedule task from event handler:
private async void OnApplicationStarted(object sender, RoutedEventArgs e)
{
await Task.Delay((int)TimeSpan.FromMinutes(9).TotalMilliseconds);
MessageBox.Show("1 minute left");
await Task.Delay((int)TimeSpan.FromMinutes(1).TotalMilliseconds);
MessageBox.Show("time over");
Application.Exit();
}
I'd use the Form.Load event with an async event handler. This will already show your form, so users will be able to see that the program has been started.
async void OnFormLoading(object sender, ...)
{
// Notify the operator that the form is loading:
this.ShowSplashScreen();
// start the delay, but do not wait yet
Task delayTask = Task.Delay(TimeSpan.FromSeconds(5));
// do other useful initializations, this might be shorter or longer than 5 seconds
DoOtherInitializations();
// now wait for the delay task to finish:
await delayTask;
this.HideSplashScreen();
}
Or an even nicer approach: show an startup-form which shows that you are starting, with only the possibility to cancel:
in class MainForm:
private async void OnFormLoading(object sender, ...)
{
// show an intro screen while doing initializations:
using (var startupForm = new FormStartup()
{
var dlgResult = startupForm.ShowDialog(this);
if (dlgResult == DialogResult.Cancel)
{
// operator cancelled starting up:
this.Close();
}
else
{
// continue starting up
}
}
}
}
}
class FormStartup
{
public void FormStartup() {...}
private async void OnFormLoading(object sender, ...)
{
Task delayTask = Task.Delay(TimeSpan.FromSeconds(5));
DoOtherInitializations();
await delayTask;
}
}

wpf c# background worker works when execution finished

I have a wpf application where I want to start a loading indicator before a task and end after task done. But the indicator starts after the task executes.
What I am trying is as follows.
private void RunAllScriptsChildwdwBtnOK_Click(object sender, RoutedEventArgs e)
{
worker.RunWorkerAsync(); // this supposed to start progress bar
_RunAllScripts_Click();
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
this.Dispatcher.Invoke(() =>
{
... Start loading indicator
});
}
private void worker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
... End loading indicator
}
But loading indicator starts and ends (as supposed in worker events) only after
_RunAllScripts_Click(); method execution is complete.
(I found that after unsubscribing from worker_RunWorkerCompleted event, progress bar starts and stays as is because no code to end it).
Also I want to add that, breakpoint hits worker_DoWork method before the execution, but UI updates after execution as I indicated above.
Thanks for all help you will be able to provide.
If i was you i would use the async + await keyword for this
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
// this is where you would enable your indicator
Button.IsEnabled = false;
await Task.Run(
() =>
{
// this is where you put your work, which should be executed in the background thread.
Thread.Sleep(2000);
});
// this is where you would disable it
Button.IsEnabled = true;
}
Using async/await will work. The await keyword will allow you to run work without affecting/blocking the UI thread (allowing message pumping to still occur). Once the work has finished, any code after the await keyword will execute.
Note that I have also wrapped the await work in an InvokeAsync call, as it appears that additional work you are doing required UI thread access.
private async void RunAllScriptsChildwdwBtnOK_Click(object sender, RoutedEventArgs e)
{
//TODO ... Start loading indicator
await Task.Run(async ()=>
{
await Application.Current.Dispatcher.InvokeAsync(()=>
{
_RunAllScripts_Click();
});
});
//TODO ... End loading indicator
}
Dear kind people helping me about this subject, thank you all.
This works for me, hope it works for all.
BackgroundWorker bwTestAll = new BackgroundWorker() { WorkerReportsProgress = true };
bwTestAll.DoWork += new DoWorkEventHandler(TestAll);
bwTestAll.RunWorkerCompleted += TestAll_RunWorkerCompleted;
//this is where I initialize my loading ring and other stuff and marshall background
//worker to do the main work
Dispatcher.Invoke(new Action(() =>
{
EnableLoading = true;
RunAllScriptsTest.IsEnabled = false;
}), DispatcherPriority.ContextIdle);
bwTestAll.RunWorkerAsync();
//this is my main work
void TestAll(object sender, DoWorkEventArgs e)
{
presenter.RunAllScripts(true);
}
//this is where I do my post-work stuff
private void TestAll_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
Dispatcher.Invoke(new Action(() =>
{
/
EnableLoading = false;
RunAllScriptsTest.IsEnabled = true;
DbExecGrid = this.ExecutionResults;
ShowOrHideExecGrid(this.EnableOrDisableGrid);
}), DispatcherPriority.ContextIdle);
}
*Please Notice that Dispatcher with "DispatcherPriority.ContextIdle" works for me.

Pause Thread While Another Thread Is Executing A Task

I created a Thread that executes a task, but i need to pause my Main thread until my secondary threads ends the task.
private void AquilesPL_Load(object sender, EventArgs e)
{
ThreadStart ts = new ThreadStart(RunTask)
Thread t = new Thread(ts);
t.Start();
SomeFunction1();
SomeFunction2();
//I need to pause the main thread here, if runtask() continue working
//if runt task ends, this main thread must to continue.
ReadFile();
CloseProgram();
}
private void RunTask()
{
//Some code that write a file
//RunTaskfunction ends, and i have to continue
}
private void ReadFile()
{
//Reading the file, this file has been written by RunTask
}
Thanks in advance.
but i need to pause my Main thread until my secondary threads ends the task.
This is typically a bad idea. A better solution is to disable the UI while the task is executing, then re-enable it when it's completed.
The TPL and async/await make this fairly straightforward. For example:
private async void AquilesPL_Load(object sender, EventArgs e)
{
var task = Task.Run(() => RunTask());
SomeFunction1();
SomeFunction2();
// Disable your UI controls
await task; // This will wait until the task completes,
// but do it asynchronously so it does not block the UI thread
// This won't read until the other task is done
ReadFile();
// Enable your UI controls here
}
If you can't use C# 5, you can do this via .NET 4 and the TPL:
private void AquilesPL_Load(object sender, EventArgs e)
{
var task = Task.Factory.StartNew(() => RunTask());
SomeFunction1();
SomeFunction2();
// Disable your UI controls
task.ContinueWith(t =>
{
// This won't read until the other task is done
ReadFile();
// Enable your UI controls here
}, TaskScheduler.FromCurrentSynchronizationContext());
}

Wait for a while without blocking main thread

I wish my method to wait about 500 ms and then check if some flag has changed. How to complete this without blocking the rest of my application?
You can use await Task.Delay(500); without blocking the thread like Sleep does, and with a lot less code than a Timer.
Thread.Sleep(500) will force the current thread to wait 500ms. It works, but it's not what you want if your entire application is running on one thread.
In that case, you'll want to use a Timer, like so:
using System.Timers;
void Main()
{
Timer t = new Timer();
t.Interval = 500; // In milliseconds
t.AutoReset = false; // Stops it from repeating
t.Elapsed += new ElapsedEventHandler(TimerElapsed);
t.Start();
}
void TimerElapsed(object sender, ElapsedEventArgs e)
{
Console.WriteLine("Hello, world!");
}
You can set AutoReset to true (or not set it at all) if you want the timer to repeat itself.
I don't really understand the question.
If you want to block before checking, use Thread.Sleep(500);
If you want to check asynchronously every x seconds, you can use a Timer to execute a handler every x milliseconds.
This will not block your current thread.
It the method in question is executing on a different thread than the rest of your application, then do the following:
Thread.Sleep(500);
System.Threading.Thread.Sleep(500);
Update
This won't block the rest of your application, just the thread that is running your method.
Using a timer should do the trick
if you need to use a thread then here is an example
void Main()
{
System.Threading.Thread check= new System.Threading.Thread(CheckMethod);
check.Start();
}
private void CheckMethod()
{
//Code
Thread.Sleep(500);
}
Asynchron Task:
var task = new Task (() => function_test()); task.Start();
public void function_test() { `Wait for 5000 miliseconds` Task.Delay(5000);` }
I've recently been struggling with the same issue where I needed an action to be run on schedule without blocking the UI.
Here's my solution:
private void Button_Click(object sender, RoutedEventArgs e)
{
RunOnSchedule(interval, cancellationToken);
}
private void RunOnSchedule(int interval, CancellationToken cancellationToken)
{
// Start the task you want to run on schedule
TaskToRunOnSchedule(args);
Task.Run(async () =>
{
// This loop checks if the task was requested to be cancelled every 1000 ms
for (int x = 0; x < interval; x+=1000)
{
if (cancellationToken.IsCancellationRequested)
{
break;
}
await Task.Delay(1000);
}
}).GetAwaiter().OnCompleted(() =>
{
// Once the task for delaying is completed, check once more if cancellation is requested, as you will reach this point regardless of if it was cancelled or not.
if (!cancellationToken.IsCancellationRequested)
{
// Run this method again
RunOnSchedule(interval, cancellationToken);
}
});
}
In a WinForms application, when I want to wait on the main thread without blocking the app, I usually use
private void Wait (double milliseconds)
{
DateTime next = System.DateTime.Now.AddMilliseconds(milliseconds);
while (next > System.DateTime.Now)
Application.DoEvents();
}

Categories