user9005650
user9005650

Reputation:

How to reduce form load time from one form to another

this is the code from my menu and it creates an instance of another form when clicked.

private void btn_AdminReg_Click(object sender, EventArgs e)
{
    this.Hide();
    Admin_Login login = new Admin_Login(1);
    login.Show();
}

it passes a parameter to varify which login wold it take (same login form is used to login to multiple forms)

in the next form the code looks something like this (Data is a class that i've defined.it has connection string and getting data form db and inserting, updating, deleting all of functions)

public partial class Admin_Login : MetroFramework.Forms.MetroForm
{
    int separator; // this is used to separate different logins

    public Admin_Login(int value)
    {
        InitializeComponent();
        separator = value;
    }

    //------- Legend ---------
    //if separator= 1 : AdminTerminal
    //if separator= 2 : UpdatingTerminal
    //if separator= 3 : View Registration
    //if separator= 4 : Registration
    //if separator= 5 : Reports
    //if separator= 6 : Cancel Union

    static string path = Path.GetFullPath(Environment.CurrentDirectory);
    static string dataBaseName = "Trade_Union_Registration.mdf";

    private void btn_Login_Click(object sender, EventArgs e)
    {
        if (separator == 1)
        {
            Data getTable = new Data();
            DataTable table = getTable.GetData("select  UserName,Password from SuperUser where UserName='" + txt_UserName.Text + "' and Password='" + txt_Password.Text + "'");

            if (table.Rows.Count == 1)
            {
                this.Hide();
                TerminalAdmin AdminTerminal = new TerminalAdmin();
                AdminTerminal.Show();
            }
            else
            {
                MetroFramework.MetroMessageBox.Show(this, "Invalid Username/Password please check your Username and Password and try again.", "Access Denied", MessageBoxButtons.OK, MessageBoxIcon.Error);
                txt_Password.Clear();
            }
        }
        else if (separator == 2)
        {
            Data getTable = new Data();
            DataTable table = getTable.GetData("select  UserName,Password from Admin_Table where UserName='" + txt_UserName.Text + "' and Password='" + txt_Password.Text + "'");

            if (table.Rows.Count == 1)
            {
                Data getter = new Data();
                DataTable dt = getter.GetData("select UserID from Admin_Table where UserName='" + txt_UserName.Text + "'");
                MessageBox.Show(dt.Rows[0][0].ToString());
                this.Hide();
                Updating form = new Updating(dt.Rows[0][0].ToString(), txt_UserName.Text);
                form.Show();
            }

when i run this code my form takes a lot of time to load one form to other form. how to solve this?

Upvotes: 0

Views: 482

Answers (1)

Christopher
Christopher

Reputation: 9804

First off, I have to agree that your approaches (Connacting SQL Queries, plain passwords) are questionable for all but the most primitive learning examples. But I am going to asume it is just one such learning example.

Nothing in the shown could should take long, but a large part of the code is missing. My best guess is that you are doing some Database Queries somewhere between the constructor and actually showing the Form. In such cases it is important to understand the "Lifecycle" of a Windows Forms Form and in what order any events are raised. Unfortunately, I have issues findign a listing like for asp.net pages. This is the closest I could get: https://learn.microsoft.com/en-us/dotnet/framework/winforms/order-of-events-in-windows-forms

If there is any code that must run after the form is first shown, put it into the Form.Shown() Event. That is it's purpose for existing.

On a general note, you will need some form of Multitasking to make this kind of application work: Database Queries, Network operations and to a lesser degree Disk operations are notoriously slow (when compared with most other actions code can do). Any approach for Multitasking/-Threading should work: BackgroundWorker, Threads, async...await pattern.

If you do not do that, you just lock up the GUI Thread. Wich to the user will be "not responding" message and not reacting to any mouse actions.

I would:

  • Add one or more background workers to this form (one per DB operation). Pick BackgroundWorker because it is a good beginners tool for learning Multitasking/-Threading.
  • Only start the background workers in with the buttons. Do not put actuall DB access code behind those buttons. If you put DB access code behinds buttons, the form can not respond until the DB access either finished or timed out.
  • Put the results onto the screen when the BackgroundWorker finishes. There is nothing you can do with regards to Progress reporting with a DB access.

Years ago I made a simple BackgroundWorker example. A few stuff like the reporting has to be cut out for this, but overall it should still put you on the right track:

#region Primenumbers
private void btnPrimStart_Click(object sender, EventArgs e)
{
	if (!bgwPrim.IsBusy)
	{
		//Prepare ProgressBar and Textbox
		int temp = (int)nudPrim.Value;
		pgbPrim.Maximum = temp;
		tbPrim.Text = "";

		//Start processing
		bgwPrim.RunWorkerAsync(temp);
	}
}

private void btnPrimCancel_Click(object sender, EventArgs e)
{
	if (bgwPrim.IsBusy)
	{
		bgwPrim.CancelAsync();
	}
}

private void bgwPrim_DoWork(object sender, DoWorkEventArgs e)
{
	int highestToCheck = (int)e.Argument;
	//Get a reference to the BackgroundWorker running this code
	//for Progress Updates and Cancelation checking
	BackgroundWorker thisWorker = (BackgroundWorker)sender;

	//Create the list that stores the results and is returned by DoWork
	List<int> Primes = new List<int>();
	

	//Check all uneven numbers between 1 and whatever the user choose as upper limit
	for(int PrimeCandidate=1; PrimeCandidate < highestToCheck; PrimeCandidate+=2)
	{
		//Report progress
		thisWorker.ReportProgress(PrimeCandidate);
		bool isNoPrime = false;

		//Check if the Cancelation was requested during the last loop
		if (thisWorker.CancellationPending)
		{
			//Tell the Backgroundworker you are canceling and exit the for-loop
			e.Cancel = true;
			break;
		}

		//Determin if this is a Prime Number
		for (int j = 3; j < PrimeCandidate && !isNoPrime; j += 2)
		{
			if (PrimeCandidate % j == 0)
				isNoPrime = true;
		}

		if (!isNoPrime)
			Primes.Add(PrimeCandidate);
	}

	//Tell the progress bar you are finished
	thisWorker.ReportProgress(highestToCheck);

	//Save Return Value
	e.Result = Primes.ToArray();
}

private void bgwPrim_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
	pgbPrim.Value = e.ProgressPercentage;
}

private void bgwPrim_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
	pgbPrim.Value = pgbPrim.Maximum;
	this.Refresh();

	if (!e.Cancelled && e.Error == null)
	{
		//Show the Result
		int[] Primes = (int[])e.Result;

		StringBuilder sbOutput = new StringBuilder();

		foreach (int Prim in Primes)
		{
			sbOutput.Append(Prim.ToString() + Environment.NewLine);
		}

		tbPrim.Text = sbOutput.ToString();
	}
	else 
	{
		tbPrim.Text = "Operation canceled by user or Exception";
	}
}
#endregion

Upvotes: 1

Related Questions