Member 7763261 Ответов: 0

Как сделать вход в систему C# с помощью background worker + progress bar


Привет,

Может ли кто-нибудь объяснить мне, как на самом деле работает фоновый работник? Я хотел бы сделать простую форму входа в систему, которая покажет прогресс входа пользователю после того, как он нажмет loggin, так как обычно требуется много времени, чтобы прочитать данные входа, поэтому я хотел бы обновить пользователя вместо того, чтобы позволить пользовательскому интерфейсу зависнуть.

Я попробовал код ниже, но я не уверен, как и где я могу сохранить результат, чтобы я мог показать пользователю, если вход в систему успешен или нет.


Любая помощь будет очень признательна.

Что я уже пробовал:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Windows.Forms;
using System.Data.OleDb;
using Excel = Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
using System.Drawing.Printing;
namespace LoginDemo
{
    public partial class Form1 : Form
    {

    
        public Form1()
        {
            InitializeComponent();
        }
        //Login will be cancelled
        private void btncancel_Click(object sender, EventArgs e)
        {
            if(backgroundWorker1.WorkerSupportsCancellation == true){
                backgroundWorker1.CancelAsync();
                btnlogin.Enabled = true;
                btncancel.Enabled = false;           
            }
        }
        //Login will be processed
        private void btnlogin_Click(object sender, EventArgs e)
        {
        
            testobj.username = txtid.Text.Trim().ToString();
            if (txtid.Text == string.Empty)
            {
                MessageBox.Show("Please enter username", "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                txtid.Focus();
            }
            else
            {
                lblMessage.Visible = true;
                progressBar1.Visible = true;

                testobj.ReadData();
                backgroundWorker1.RunWorkerAsync();
                btnlogin.Enabled = false;
                btncancel.Enabled = true;
              /*  if (chckrbm.Checked == true)
                {
                    IMACBOX.Properties.Settings.Default.loginUsername = username;
                    IMACBOX.Properties.Settings.Default.Save();
                }*/

             //  ReadData(connectionString);
            }
            
            
            
            
          

        }
        // Will handle the heavy work
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {

            int dataload = 0;
            for (dataload = 0; dataload <= 100; dataload++)
            {
                if (backgroundWorker1.CancellationPending == true)
                {
                   
                    //user clicked cancel button
                    e.Cancel = true;
                    backgroundWorker1.ReportProgress(0);
                   break;
                }
                else {
                    //do the heavywork
                   // ReadDatas();
                  //  dataload += 1;
                   // testobj.ReadData();
                    backgroundWorker1.ReportProgress(dataload);//Report progress
                }
            }
            e.Result = dataload;
        }
        // Will update progressbar on heavy work progress
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            //Updater progress bar

           
            progressBar1.Value = e.ProgressPercentage;
            lblMessage.Text = "Loading..." + e.ProgressPercentage.ToString() + " %";
            
        }
        // Will update when progress is completed
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //Check progress before displaying message

            if (e.Cancelled == true)
            {
                MessageBox.Show("Operation Cancelled ", "Cancelled ", MessageBoxButtons.OK, MessageBoxIcon.Information);
                progressBar1.Value = 0; // Reset progressbar value if user cancelled
                lblMessage.Text = "";//clear the label
                progressBar1.Visible = false;
            }
            else if (e.Error != null)
            {

               // String somethingwrong = e.Result.ToString();
                MessageBox.Show(e.Error + "Error found " + e.Error.Message , "Error ", MessageBoxButtons.OK, MessageBoxIcon.Error);
                progressBar1.Value = 0; // Reset progressbar value if user cancelled
                lblMessage.Text = "";//clear the label

            }
            else {
                MessageBox.Show("Progress done " + e.Result.ToString() + " ","Done ",MessageBoxButtons.OK,MessageBoxIcon.Information);
                progressBar1.Value = 0; // Reset progressbar value if user cancelled
                lblMessage.Text = "";//clear the label
            }
        }
        //Method for doing the heavy work
        private void ReadDatas() {
            try {

                Thread.Sleep(100);


            }catch(Exception e){

                MessageBox.Show("Login Result ", e.Message , MessageBoxButtons.OK,MessageBoxIcon.Information);
                progressBar1.Value = 0; // Reset progressbar value if user cancelled
                lblMessage.Text = "";//clear the label
            }
        }

      

        private void Form1_Load(object sender, EventArgs e)
        {
          //  username = txtid.Text.Trim();
         //   status = lblMessage.Text.ToString();
          //  bar = progressBar1.Value;
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Windows.Forms;
using System.Data.OleDb;
using Excel = Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
using System.Drawing.Printing;
using System.Data;
namespace LoginDemo
{
    class testobj
    {

        public static String username, lastname, firstname, status, lblMessage;
        public static int progressBar1Value = 0;
        public static string connectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\IMAC\APP\IMACDB\FormDB2.xlsx;Extended Properties='Excel 12.0;HDR=Yes;'";
        // public string connectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=\\132.186.144.184\d$\FormDB4.xlsx;Extended Properties='Excel 12.0;HDR=Yes;'";
        //   public string connectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=\\132.186.144.239\d$\IMAC\APP\IMACDB\FormDB2.xlsx;Extended Properties='Excel 12.0;HDR=Yes;'";
        public static OleDbConnection cnn;
        public static OleDbCommand cmd;
        public static OleDbDataAdapter da;
        public static OleDbDataReader dr;
        public DataSet dstResults = new DataSet();
        public DataView myView;
        public DataTable dtable;
        public DataColumn c;
    
     public static  void ReadData()
        {

            try
            {
             
                string queryString = "SELECT Employee_ID,LastName,FirstName FROM [Entries$] WHERE Employee_ID ='" + username.Trim().ToString() + "'";
                dr = null;
                cnn = new OleDbConnection(connectionString);
                cmd = new OleDbCommand(queryString, cnn);
                cnn.Open();
                dr = cmd.ExecuteReader();



            
                
                if (dr.Read() == true)
                {
              
                    Thread.Sleep(100);
                    // MessageBox.Show("Progress bar");
                    firstname = dr[1].ToString();
                    lastname = dr[2].ToString();
                    MessageBox.Show("Login successfull"); 
            
                }
                else
                {
                    MessageBox.Show("Username Invalid", "Error Message");

                }
                // Always call Close when done reading.
                dr.Close();
            }
            //  }
            catch (Exception e)
            {
                MessageBox.Show("Error " + e.Message, "Error");
            }
         

       }
    }
}

Richard Deeming

"Я не уверен, как и где я могу сохранить результат"

В e.Result - как это уже делает ваш код.

В чем проблема?

Member 7763261

Привет Ричард,

Спасибо за ваш ответ. Пожалуйста, голые со мной, как я новичок в дело управления backgroundworker. Похоже, что мой progressbar выполняется только после того, как отнимает много времени код, из которого я хотел бы обновить индикатор выполнения, чтобы пользователь знал, что данные загружаются. как мне получить результат из этого объекта e?

Richard Deeming

Основываясь на опубликованном вами коде, вся работа закомментирована, поэтому будет невозможно увидеть, обновляется ли индикатор выполнения во время работы рабочего.

Member 7763261

Я раскомментировал testobj. ReadData (), а также использовал lblMessage из моего класса testobj для отображения сообщений, но progressbar запускается только после этого. теперь мне нужно объявить use progressBar1Value из моего класса testobj, чтобы также удерживать прогресс. потому что из того, что я прочитал, я не могу получить доступ к элементам управления пользовательским интерфейсом из dowork

Richard Deeming

Вы дважды проверили, что WorkerReportsProgress свойство имеет значение true?

Member 7763261

Да он установлен в true

Richard Deeming

Что ж, это странно. То ReportProgress / ProgressChanged для меня это прекрасно работает.

И чтобы ответить на ваш другой вопрос, нет, вы не можете напрямую получить доступ или изменить элементы управления из DoWork метод или любой метод, вызванный из него. Вы можете только вызвать ReportProgress метод и обновление элементов управления из ProgressChanged обработчик событий или используйте Invoke метод для запуска небольшого метода в потоке пользовательского интерфейса для обновления элемента управления.

Member 7763261

Очень, но я закомментировал testobj.ReadData(); на событии btnlogin_Click и вызвал его на dowork, но я застрял внутри цикла. Есть идеи, что я делаю не так. и спасибо за статью о SQL-инъекции. очень информативный.

Richard Deeming

В коде, который вы опубликовали, нет ничего, что могло бы создать бесконечный цикл.

Member 7763261

Хорошо, MessageBox. show, который я показываю из своего класса testobj ? находятся ли они в нужном месте, если я хочу показать пользователю, что пошло не так, или они находятся не в том месте?

Richard Deeming

Они вероятно работа, но вы отображаете пользовательский интерфейс из потока, не являющегося пользовательским интерфейсом.

Я был бы склонен удалить try..catch блок, и пусть исключение фильтруется до конца. RunWorkerCompleted обработчик событий.

Я также был бы склонен изменить метод, чтобы вернуть a bool указывает, был ли вход в систему успешным, а не отображает сообщение. Затем сохраните этот результат в e.Result недвижимость в DoWork метод, прочтите его в RunWorkerCompleted метод, и, наконец, отобразить сообщение об успехе/неудаче там, как только вы вернетесь в поток пользовательского интерфейса.

Member 7763261

Привет Ричард,

Спасибо вам за всю вашу помощь. В конце концов мне удалось исправить код, но я возвращаю строку вместо bool. Пожалуйста, поделитесь, почему вы предпочитаете возвращать bool вместо string?

Richard Deeming

Потому что легче проверить bool чтобы увидеть, удалось ли войти в систему, и отобразить соответствующее сообщение, чем проверить string.

Помимо всего прочего, если вы изменили сообщение, но забыли обновить тест, каждый логин вдруг сработает, в том числе и недействительный.

Richard Deeming

Кроме того, ваш код уязвим для SQL-инъекция[^]. НИКОГДА используйте конкатенацию строк для построения SQL-запроса. ВСЕГДА используйте параметризованный запрос.

Все, что вы хотели знать о SQL-инъекции (но боялись спросить) | Трой Хант[^]
Как я могу объяснить SQL-инъекцию без технического жаргона? | Обмен Стеками Информационной Безопасности[^]
Шпаргалка по параметризации запросов / OWASP[^]

0 Ответов