This is what I have got:
Thread t = new Thread(new ThreadStart(LoginForm));
t.Start();
Thread.Sleep(7500);
t.Abort();
InitializeComponent();
public void LoginForm()
{
Application.Run(new frmLoginForm());
}
How can I make the thread wait until the form closes before aborting the thread.
You can use ShowDialog() method to display the form, here is the MSDN
Or
Better to Declare Thread as public and only abort the Thread in the form closing event
Thread t = new Thread(new ThreadStart(LoginForm));
t.Start();
InitializeComponent();
public void LoginForm()
{
LoginForm frmLogin=new LoginForm();
DialogResult dr = frmLogin.ShowDialogue();
if (dr == DialogResult.Yes)
{
t.Abort();
}
}
and in the form closing event set the DialogResult property as
this.DialogResult = DialogResult.Yes;
You can try something like this,
var frmLogin = new FrmLogin();
if (frmLogin.ShowDialog() == DialogResult.OK)
{
Application.Run(new frmMainForm());
}
and in you frmLogin if login is OK then set the from dialog result as DialogResult.OK
Continuing SumeshK's solution, I will take lil different approach:
public void SomeMethod()
{
Thread t = new Thread(new ThreadStart(LoginForm));
t.Start();
t.Join();
InitializeComponent();
}
public void LoginForm()
{
LoginForm frmLogin=new LoginForm();
frmLogin.ShowDialog();
}
The method ShowDialog itself will block your thread from terminating/finishing. This should work. But I doubt about the InitializeComponent() method. what is it for?
Related
I have a SplashScreen that should be shown in front of all other windows in the application.
Since it is a SplashScreen, this cannot be modal dialog. Instead, this should be shown by mean of other thread.
I create the splash screen this way:
SplashScreenForm = new SplashScreen(mainForm);
// SplashScreenForm.TopMost = true;
And to show it, I am using this call, called from a different thread:
Application.Run(SplashScreenForm);
If I uncomment SplashScreenForm.TopMost = true, the splash is shown on top of other windows, even on top of windows belonging to different applications.
If you want to know how the thread is created:
public void ShowSplashScreen()
{
SplashScreenThread = new Thread(new ThreadStart(ShowForm));
SplashScreenThread.IsBackground = true;
SplashScreenThread.Name = "SplashScreenThread";
SplashScreenThread.Start();
}
private static void ShowForm()
{
Application.Run(SplashScreenForm);
}
How can I do it?
Something like:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Thread splashThread = new Thread(new ThreadStart(
delegate
{
splashForm = new SplashForm();
Application.Run(splashForm);
}
));
splashThread.SetApartmentState(ApartmentState.STA);
splashThread.Start();
// Load main form and do lengthy operations
MainForm mainForm = new MainForm();
mainForm.Load += new EventHandler(mainForm_Load);
Application.Run(mainForm);
}
Then later after time-consuming operations are ended:
static void mainForm_Load(object sender, EventArgs e)
{
if (splashForm == null)
return;
splashForm.Invoke(new Action(splashForm.Close));
splashForm.Dispose();
splashForm = null;
}
This will start your splash screen before your main form and only dismiss it when the lengthy operations are completed in mainForm_Load.
You can try calling function SetForegroundWindow(HWND) from WinAPI :
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
// somewhere in the code :
SetForegroundWindow(SplashScreenForm.Handle);
I am having an issue with a background worker.
When i'm cancelling the backgroundworker, it closes the form too, i don't want it.
I just want to stop the backgroundworker, and keep the form on the screen, and saying a message to the user like "Program stopped by user"
public BackgroundWorker bw = new BackgroundWorker() { WorkerSupportsCancellation = true };
public Form1()
{
bw.WorkerSupportsCancellation = true;
InitializeComponent();
}
private void stopChild_Click(object sender, EventArgs e)
{
if (bw.IsBusy)
{
bw.CancelAsync();
this.Dispose();
}
}
public void startParListe()
{
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
if (bw.IsBusy != true)
bw.RunWorkerAsync();
}
public void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker ;
for (int i = 0; i < countPlages; i++)
{
if ((worker.CancellationPending == true))
{
e.Cancel = true;
}
#do something else
}
}
So, when the user click on the "stopChild" button, it is supposed to send a CancelSignal to my BWorker.
Everytime my BWorker is working, i'm checking for this CancellationPending Signal before doing anything.
With this code, the form closes when clicking on the "stopChild"
And when i remove the "this.Dispose()", the BWorker doesn't stop. Why ?
You don't properly process the CancellationPending:
if ((worker.CancellationPending == true))
{
e.Cancel = true;
}
I am not sure what e.Cancel is supposed to do, but you still continue to do work in your for loop since you don't leave the loop. Change it to:
if (worker.CancellationPending) // btw - avoid unnecessarily verbous code
{
break;
}
The backgroundworker does not close your form, this.Dispose does. You need to omit it. The reason why this.Dispose helped stop the background worker is because it is owned by the form, so closing the form also closees the worker. But once you fix the cancellation as described above, you should not need Dispose any longer
You should break out of the loop when you set e.Cancel to true (also, this.Dispose() is closing your form:
public void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker ;
for (int i = 0; i < countPlages; i++)
{
if ((worker.CancellationPending == true))
{
e.Cancel = true;
break;
}
#do something else
}
}
I am working on C# win form application.My problem is when i click on menu i created one separate thread which is showing the progress(splash progress form). When i abort thread, progress form still display..! but when i move mouse pointer over the form it disappear
immediately..!
Following is my code
Thread progressThread = new Thread(() => Application.Run(new frmOperationProgress()));
progressThread.IsBackground = true;
progressThread.Start();
//Some work
progressThread.Abort();
How to close this progress form object in c#
The problem is using Abort - it's not generally recommended because there is no guarantee that it's going to do what you expect (in your case hide the form).
Best to add proper cancellation support into your thread and handle hiding the splash screen directly.
Please never ever use Abort(). This kind of work is best done trough BackgroundWorker; if you insist on Thread
Try:
var form = new frmOperationProgress();
Thread progressThread = new Thread(() => Application.Run(form));
progressThread.IsBackground = true;
progressThread.Start();
//Some work
form.ExternalClose();
Where ExternalClose is method of form like this:
public void ExternalClose() {
if (InvokeRequired) {
Invoke(new MethodInvoker(() => { ExternalClose(); }));
} else {
Close();
}
}
Solution using BackgroundWorker:
In backround worker you have to do UI stuff in ProgressChanged event (which is running in UI thread) and do the dirty work in DoWork event (background thread).
FormMain.cs: (Form with single BackgroundWorker control, named "backgroundWorker1", with wired up events backgroundWorker1_DoWork, backgroundWorker1_ProgressChanged and WorkerReportsProgress set to true)
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
namespace ConsoleApplication1 {
public partial class FormMain : Form {
private FormProgress m_Form;
public FormMain() {
InitializeComponent();
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {
backgroundWorker1.ReportProgress(0, "hello");
Thread.Sleep(2000);
backgroundWorker1.ReportProgress(20, "world");
Thread.Sleep(2000);
backgroundWorker1.ReportProgress(40, "this");
Thread.Sleep(2000);
backgroundWorker1.ReportProgress(60, "is");
Thread.Sleep(2000);
backgroundWorker1.ReportProgress(80, "simple");
backgroundWorker1.ReportProgress(100, "end");
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) {
if (e.ProgressPercentage == 0 && m_Form == null) {
m_Form = new FormProgress();
m_Form.Show();
}
if (e.ProgressPercentage == 100 && m_Form != null) {
m_Form.Close();
m_Form = null;
return;
}
var message = (string)e.UserState;
m_Form.UpdateProgress(e.ProgressPercentage, message);
}
}
}
Where FormProgress is simple form with ProgressBar progressBar1 and Label label1 and one extra method:
public void UpdateProgress(int percentage, string message) {
this.progressBar1.Value = percentage;
this.label1.Text = message;
}
You can just close your form and the thread (which is blocked by the message loop of that form) will be ended naturally:
var yourForm = new frmOperationProgress();
//Start it
Thread progressThread = new Thread(() => Application.Run(yourForm));
progressThread.IsBackground = true;
progressThread.Start();
//....
//close it
yourForm.Invoke((Action)(() => yourForm.Close()));
I am loading MainWindow in App_Startup (). I wanted to show the progress bar while loading the window. But it is not working :
void App_Startup(object sender, StartupEventArgs e)
{
Thread bootStrapThread = new Thread(new ThreadStart(runBootStrapProcess));
bootStrapThread.SetApartmentState(ApartmentState.STA);
bootStrapThread.IsBackground = true;
bootStrapThread.Start();
_loadingProgressBar = new loadingProgressBar();
_loadingProgressBar.ShowDialog();
}
I want to load the window from thread :
void runBootStrapProcess()
{
MetadataReader mr = new MetadataReader();
if (currentVersionNo.Equals(remoteVersionNo))
{
Application.Current.Shutdown();
}
else
{
MainWindow mw = new MainWindow();
mw.Show();
}
_loadingProgressBar.ShouldCloseNow = true;
}
You can try this:
void runBootStrapProcess() {
MetadataReader mr = new MetadataReader();
if (currentVersionNo.Equals(remoteVersionNo)) {
Application.Current.Shutdown();
} else {
System.Windows.Application.Current.Dispatcher.BeginInvoke(
new Action(
() => {
MainWindow mw = new MainWindow();
mw.Show();
}));
}
_loadingProgressBar.ShouldCloseNow = true;
}
You basically from the thread when you want to show the window send it to the main application thread. This thus stops the application from closing down when the thread exits since the MainWindow is Shown from the main thread.
I suspect the window is missing the message pump since the WPF Application class with its Dispatcher is running on a different STA Thread
In my Project I included a splash-screen.
For that i wrote below code in Login Window Contractor. The Splash Screen is working perfectly. But after login, the main page is opened. if it is closed, then login is opened.
In that the Splash Screen is cross the Login page. I don't want this.
How to do this: Splash Screen Shown only once in my project?
Help me...
public LogIn()
{
InitializeComponent();
Thread th = new Thread(new ThreadStart(Splash));
th.Start();
Thread.Sleep(3000);
th.Abort();
Thread.Sleep(1000);
}
private void Splash()
{
Welcome sp = new Welcome();
sp.ShowDialog();
}
private void Form1_Load(object sender, EventArgs e)
{
SplashScreen Splash = new SplashScreen();
Splash.Show();
}
if you want the SplashScreen to close after 3 Seconds then use a timer in the SplashScreen and after 3 Seconds user this.close()
You can possibly pass a boolean parameter which will instruct the Login Constructor to display or not to display the Splash Screen.
public LogIn(boolean splashOpened)
{
InitializeComponent();
if(!splashOpened) //If Splash Screen is not opened , Open it
{
Thread th = new Thread(new ThreadStart(Splash));
th.Start();
Thread.Sleep(3000);
th.Abort();
Thread.Sleep(1000);
}
}
private void Splash()
{
Welcome sp = new Welcome();
sp.ShowDialog();
}
private static Welcome sp;
public LogIn()
{
InitializeComponent();
if (sp == null)
{
Thread th = new Thread(new ThreadStart(Splash));
th.Start();
Thread.Sleep(3000);
th.Abort();
Thread.Sleep(1000);
}
}
private void Splash()
{
if (sp == null)
{
sp = new Welcome();
sp.ShowDialog();
}
}