Reputation: 5257
In my C# program there is a "Login" function. When user presses on the button - program uses given login/pas info to login on a certain website using POST url and to save cookies. The webpage after login is then further processed in my program. Then, the result is shown to the user.
The problem is - the moment user clicks on a button - whole program hangs up and is waiting until operation from above is accomplished. That's about 3-5 seconds of inactivity.
I'd like to block user input during that time and to prompt with the message, for example "working...". Othervise there is no way to tell is the program is actually working on something or not. Here's what I mean:
What techniques should I use to achieve the desired goal?
Upvotes: 4
Views: 316
Reputation: 8550
UI is blocked, because you are running login code in UI thread. To avoid that, you may use 'BackgroundWorker', or if you're using 4 or 4.5 .NET you may use 'Tasks' to move your login stuff to another thread to avoid UI blocking.
If Windows Forms and .NET 4+, following may work:
private void button1_Click(object sender, EventArgs e)
{
progressBar1.Visible = true;
Task.Factory.StartNew(Login)
.ContinueWith(t =>
{
progressBar1.Visible = false;
}, TaskScheduler.FromCurrentSynchronizationContext());
}
private static void Login()
{
// should replace this with actual login stuff
Thread.Sleep(TimeSpan.FromSeconds(3));
}
What it does, it moves Login processing to another thread, so UI thread is not blocked. Before staring login, it unhides progress bar, which has style set to marque and after Login is finished, it hides progress bar again.
As long as UI is not blocked, user is allowed to input/press anything he wants during login, so solution would be either disable all controls before login or show progress bar in separate modal form, in such way user won't see application as hanged and won't be able to do any input until progress bar form will be closed.
Update: added example with separate progress form:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MarqueeForm.DoWithProgress("Doing login", Login);
}
private static void Login()
{
Thread.Sleep(TimeSpan.FromSeconds(3));
}
}
public class MarqueeForm : Form
{
private Label label;
public MarqueeForm()
{
var progressBar = new ProgressBar
{
Style = ProgressBarStyle.Marquee,
Top = 20,
Size = new Size(300, 15)
};
Controls.Add(progressBar);
label = new Label();
Controls.Add(label);
}
public static void DoWithProgress(string title, Action action)
{
var form = new MarqueeForm
{
Size = new Size(310, 50),
StartPosition = FormStartPosition.CenterParent,
FormBorderStyle = FormBorderStyle.FixedDialog,
ControlBox = false,
label = { Text = title }
};
form.Load += (sender, args) =>
Task.Factory.StartNew(action)
.ContinueWith(t => ((Form)sender).Close(),
TaskScheduler.FromCurrentSynchronizationContext());
form.Show();
}
}
Upvotes: 2
Reputation: 1064
I guess the question is about a Forms application?
If so, you can setup your form to the "loading screen" then do a Application.Doevents(); then start your process. After it's done you can remove your "loading screen".
Upvotes: 0
Reputation: 81
When pressing the button you can disable the button button1.Enable = false;
while displaying message like "Please wait..". Enable button when process finish and display result.
Upvotes: 0