How can I display a loading control while a process is waiting for be finished?
You create a thread, which simply sets two properties and then ends. The t.Abort
will probably do nothing, since the thread will have been exited by that time. Even worse, you import the excel file on the UI thread, which blocks any animation and freezes the complete UI.
This is how you should make it:
Remark: Of course if your form is responsive, you must disable/enable the controls and prepare to the case what happens if your form is being closed during the load.
1. Using threads
If you really want to explicitly use threads, do it like this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private Thread workerThread = null;
private void btnImport_Click(object sender, EventArgs e)
{
// start the animation (I used a progress bar, start your circle here)
progressBar1.Visible = true;
progressBar1.Style = ProgressBarStyle.Marquee;
// start the job and the timer, which polls the thread
btnImport.Enabled = false;
workerThread = new Thread(LoadExcel);
workerThread.Start();
timer1.Interval = 100;
timer1.Start();
}
private void LoadExcel()
{
// some work takes 5 sec
Thread.Sleep(5000);
}
private void timer1_Tick(object sender, EventArgs e)
{
if (workerThread == null)
{
timer1.Stop();
return;
}
// still works: exiting
if (workerThread.IsAlive)
return;
// finished
btnImport.Enabled = true;
timer1.Stop();
progressBar1.Visible = false;
workerThread = null;
}
}
2. Background worker
The BackgroundWorker
can throw an event when it is finished:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
backgroundWorker1.DoWork += BackgroundWorker1_DoWork;
backgroundWorker1.RunWorkerCompleted += BackgroundWorker1_RunWorkerCompleted;
}
private void btnImport_Click(object sender, EventArgs e)
{
// start the animation
progressBar1.Visible = true;
progressBar1.Style = ProgressBarStyle.Marquee;
// start the job
btnImport.Enabled = false;
backgroundWorker1.RunWorkerAsync();
}
private void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
LoadExcel();
}
private void BackgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
btnImport.Enabled = true;
progressBar1.Visible = false;
}
private void LoadExcel()
{
// some work takes 5 sec
Thread.Sleep(5000);
}
}
3. Using async-await
This is the simplest one.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private async void btnImport_Click(object sender, EventArgs e)
{
// start the waiting animation
progressBar1.Visible = true;
progressBar1.Style = ProgressBarStyle.Marquee;
// simply start and await the loading task
btnImport.Enabled = false;
await Task.Run(() => LoadExcel());
// re-enable things
btnImport.Enabled = true;
progressBar1.Visible = false;
}
private void LoadExcel()
{
// some work takes 5 sec
Thread.Sleep(5000);
}
}
Wait until form is finished loading
try to use the shown event something like this
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Shown += new System.EventHandler(this.Form1_Shown);
}
private void Form1_Shown(object sender, EventArgs e)
{
}
}
hope this help
Best way to display a progress form while a method is executing code?
A BackgroundWorker
is a great way to perform a long running operation without locking the UI thread.
Use the following code to start a BackgroundWorker and display a loading form.
// Configure a BackgroundWorker to perform your long running operation.
BackgroundWorker bg = new BackgroundWorker()
bg.DoWork += new DoWorkEventHandler(bg_DoWork);
bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);
// Start the worker.
bg.RunWorkerAsync();
// Display the loading form.
loadingForm = new loadingForm();
loadingForm.ShowDialog();
This will cause the following method to be executed on a background thread. Note that you cannot manipulate the UI from this thread. Attempting to do so will result in an exception.
private void bg_DoWork(object sender, DoWorkEventArgs e)
{
// Perform your long running operation here.
// If you need to pass results on to the next
// stage you can do so by assigning a value
// to e.Result.
}
When the long running operation completes, this method will be called on the UI thread. You can now safely update any UI controls. In your example, you would want to close the loading form.
private void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Retrieve the result pass from bg_DoWork() if any.
// Note, you may need to cast it to the desired data type.
object result = e.Result;
// Close the loading form.
loadingForm.Close();
// Update any other UI controls that may need to be updated.
}
Create a loading bar
Putting a Thread.Sleep
(or any long-running piece of code) in your event handler will block the UI until that event handler is done running its code.
You have to put such code in a BackgroundWorker
, Thread
or Task
and run that code asynchronously. In that way, the code can run independently from the UI, which will make the UI responsive.
How do I show a Loading . . . please wait message in Winforms for a long loading form?
Using a separate thread to display a simple please wait message is overkill especially if you don't have much experience with threading.
A much simpler approach is to create a "Please wait" form and display it as a mode-less window just before the slow loading form. Once the main form has finished loading, hide the please wait form.
In this way you are using just the one main UI thread to firstly display the please wait form and then load your main form.
The only limitation to this approach is that your please wait form cannot be animated (such as a animated GIF) because the thread is busy loading your main form.
PleaseWaitForm pleaseWait=new PleaseWaitForm ();
// Display form modelessly
pleaseWait.Show();
// ALlow main UI thread to properly display please wait form.
Application.DoEvents();
// Show or load the main form.
mainForm.ShowDialog();
Show Loading animation during loading data in other thread
When the form is frozen, it means the UI thread is too busy and so even if you try to show a loading animation, it will not animate. You should load data asynchronously.
You can have an async
method which returns Task<DataTable>
like the GetDataAsync
method which you can see in this post. Then call it in an async
event handler. In the event handler, first show the loading image, then load data asynchronously and then hide the loading image.
You can simply use a normal PictureBox
showing a gif animation as loading control. Also you may want to take a look at this post to show a transparent loading image.
public async Task<DataTable> GetDataAsync(string command, string connection)
{
var dt = new DataTable();
using (var da = new SqlDataAdapter(command, connection))
await Task.Run(() => { da.Fill(dt); });
return dt;
}
private async void LoadDataButton_Click(object sender, EventArgs e)
{
loadingPictureBox.Show();
loadingPictureBox.Update();
try
{
var command = @"SELECT * FROM Category";
var connection = @"Your Connection String";
var data = await GetDataAsync(command, connection);
dataGridView1.DataSource = data;
}
catch (Exception ex)
{
// Handle Exception
}
loadingPictureBox.Hide();
}
Display loading content/image while waiting
When you say displaying loading message, I interpret that you're using ajax. In ajax start you can display that image, and in ajax complete callback you can hide the loading image. Please provide some code examples if possible.
In case if jQuery ajax, you can use:
$('#loaderImage').show();
$.ajax({
// Other ajax parameters
success: function () {
// hiding the image here
$('#loaderImage').hide();
}
});
How can I create a Please Wait, Loading... animation using jQuery?
You could do this various different ways. It could be a subtle as a small status on the page saying "Loading...", or as loud as an entire element graying out the page while the new data is loading. The approach I'm taking below will show you how to accomplish both methods.
The Setup
Let's start by getting us a nice "loading" animation from http://ajaxload.info
I'll be using
Let's create an element that we can show/hide anytime we're making an ajax request:
<div class="modal"><!-- Place at bottom of page --></div>
The CSS
Next let's give it some flair:
/* Start by setting display:none to make this hidden.
Then we position it in relation to the viewport window
with position:fixed. Width, height, top and left speak
for themselves. Background we set to 80% white with
our animation centered, and no-repeating */
.modal {
display: none;
position: fixed;
z-index: 1000;
top: 0;
left: 0;
height: 100%;
width: 100%;
background: rgba( 255, 255, 255, .8 )
url('http://i.stack.imgur.com/FhHRx.gif')
50% 50%
no-repeat;
}
/* When the body has the loading class, we turn
the scrollbar off with overflow:hidden */
body.loading .modal {
overflow: hidden;
}
/* Anytime the body has the loading class, our
modal element will be visible */
body.loading .modal {
display: block;
}
And finally, the jQuery
Alright, on to the jQuery. This next part is actually really simple:
$body = $("body");
$(document).on({
ajaxStart: function() { $body.addClass("loading"); },
ajaxStop: function() { $body.removeClass("loading"); }
});
That's it! We're attaching some events to the body element anytime the ajaxStart
or ajaxStop
events are fired. When an ajax event starts, we add the "loading" class to the body. and when events are done, we remove the "loading" class from the body.
See it in action: http://jsfiddle.net/VpDUG/4952/
Related Topics
Application Can't Scaffold Items
How Does Java's Use-Site Variance Compare to C#'s Declaration Site Variance
Update Float Array from C++ Native Plugin
Get List of Certificates from the Certificate Store in C#
Why Can't I Retrieve an Item from a Hashset Without Enumeration
How to Explain C++ Pointers to a C#/Java Developer
Getters, Setters, and Properties Best Practices. Java VS. C#
Change Forecolor Af a Special Word in Gridview Cell
.Net Vs Java Garbage Collector
Custom Model Binder for a Property
Method Overloading. Can You Overuse It
Sort Datagridview Columns in C#? (Windows Form)
Instantiating a Python Class in C#
C# Invalid Attempt to Call Read When Reader Is Closed