0

I have created a application where multiple people scan QR codes on products before dispatching.

The application is created using WinForms, C# language and SQL Database.

I am using MDI form with multiple forms like scan products, Generate MIS, Dashboard etc.

The application is running pretty well, now I am working on the optimization.

I am stuck in the Dashboard form, which contains multiple pivot count from the database like Scan per Users, Scan per product, Scanning done per hour etc.

The form is working fine but loading so much data takes some time in which I want to show a animated gif untill the process is executed and the listviews and labels are updated.

Using the below code the image is not visible, when the code is run in the background. Please guide what I need to do.

I have pasted only one method for example others are similar:

  private void RefreshBtn_Click(object sender, EventArgs e)
    {
         Cursor.Current = Cursors.WaitCursor;
         pictureBox2.Visible = true;
         displayStats();
         Cursor.Current = Cursors.Arrow;
         pictureBox2.Visible = false;
    }

private void displayStats()
    {
    CustScan();
    DatewiseQcCount();
    UserWiseScan();
    UserwiseDScan();
    DayWiseDispatchScan();
    HourwiseQcCount();
    }

private void UserWiseScan()
    {
        string queryString = "select scanby,count(distinct refno),count(1) from SecRec where scan='Y' group by scanby order by 3,2 desc";
        lstVUser.Clear();
        lstVUser.Columns.Add("User", 105);
        lstVUser.Columns.Add("Cust", 60);
        lstVUser.Columns.Add("Imp", 60);

        using (SqlConnection conn = new SqlConnection(connectString))
        {
            SqlCommand cmd = new SqlCommand(queryString, conn);
            try
            {
                conn.Open();
                SqlDataAdapter adp = new SqlDataAdapter(queryString, conn);
                DataTable dt = new DataTable();
                adp.Fill(dt);
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    DataRow dr = dt.Rows[i];
                    ListViewItem listitem = new ListViewItem(dr[0].ToString());
                    listitem.SubItems.Add(dr[1].ToString().PadLeft(3));
                    listitem.SubItems.Add(dr[2].ToString().PadLeft(3));
                    lstVUser.Items.Add(listitem);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

    }

There is not much activity in the fornt end as return rows are limited. The majority of the process is being done in the backend.

I want to show the pictureBox with animated GIF.

Danish_k12
  • 329
  • 2
  • 3
  • 20
  • Google about backgroundworker in c#, you'll get an idea – Bayeni Jul 14 '15 at 10:05
  • I tried background worker, but I need to pass so many value to the listview and labels not looks feasible. Cross-threading issues. – Danish_k12 Jul 14 '15 at 10:07
  • i have already seen the below post. I am find it hard to implement the same in the above. Can you please guide me how to use the same in the above example. – Danish_k12 Jul 14 '15 at 10:17
  • There is a hacky way you can try. Check this thread http://stackoverflow.com/questions/15516014/is-it-good-idea-to-use-control-checkforillegalcrossthreadcalls-false but that workaround is generally frowned upon. – Wolf5 Jul 14 '15 at 10:21
  • @Wolf5 The solution is not for me. – Danish_k12 Jul 14 '15 at 10:31
  • Is the image box visible at all? Make sure it's on top of all other controls on your form. If it is an animated Gif it will animate on its own as long as the UI thread is not busy. Also. Do not set visible to false until the background thread is done. Check http://stackoverflow.com/questions/14455293/how-to-and-when-use-async-and-await for another way to run your code in the background. – Wolf5 Jul 14 '15 at 10:44
  • Add a background worker, assign the DoWork handler to your displayStats, method, and set the event.result to what you want to display, then on the RunWorkerCompleted event assign a method to update the UI with the data in event.result – BhavO Jul 14 '15 at 10:54
  • @Wolf5 The picturebox is top of all controls. – Danish_k12 Jul 14 '15 at 11:13
  • Remove the line pictureBox2.Visible = false; and see if it shows then. Be 100% sure that it has been set to visible (breakpoint). – Wolf5 Jul 14 '15 at 11:24
  • Yes. It shows. The problem is only while the background process is executed. – Danish_k12 Jul 15 '15 at 10:17
  • Did you remove the visible=false? I suspect you are using the code as you have shown. Which means as soon as you start your work you are showing and immediately hiding it again. Remove any chance for the control to get hidden. Are you working with multiple forms or just one? If multiple make sure the one with the picture box is topmost. – Wolf5 Jul 16 '15 at 21:15
  • Using only one form. Have done the necessary changes to no avail. – Danish_k12 Jul 17 '15 at 12:46
  • How do you run the code in the background? The example code is in the foreground (UI thread). – Wolf5 Jul 17 '15 at 20:32
  • `pictureBox2.Visible = true;` is not visible?? – Jaydip Jadhav Mar 23 '16 at 10:56

2 Answers2

0

Add a BackgroundWorker worker, assign the DoWork handler to your displayStats, method, and set the event.result to what you want to display, then on the RunWorkerCompleted event assign a method to update the UI with the data in event.result

Hope this helps:

Backgorund worker:

http://www.codeproject.com/Articles/99143/BackgroundWorker-Class-Sample-for-Beginners

http://www.codeproject.com/Articles/228869/BackgroundWorker-and-UI-threads

BhavO
  • 2,406
  • 1
  • 11
  • 13
0

You need to create one form that is frmloading here.. you need to create object of that form and called using threading concept..and in FrmLoading put one Picturebox and set .gif image in it.

FrmLoading f2 = new FrmLoading();
using (new PleaseWait(this.Location, () =>MethodWithParameter())) {  f2.Show(this); }
f2.Close();

As shown above code you need to create PleaseWait class.

PleaseWait.cs

public class PleaseWait : IDisposable
{
    private FrmLoading mSplash;
    private Point mLocation;

    public PleaseWait(Point location, System.Action methodWithParameters)
    {
        mLocation = location;
        Thread t = new Thread(new ThreadStart(workerThread));
        t.IsBackground = true;
        t.SetApartmentState(ApartmentState.STA);
        t.Start();
        methodWithParameters();
    }
    public void Dispose()
    {
        mSplash.Invoke(new MethodInvoker(stopThread));
    }
    private void stopThread()
    {
        mSplash.Close();
    }
    private void workerThread()
    {
        mSplash = new FrmLoading();   // Substitute this with your own
        mSplash.StartPosition = FormStartPosition.CenterScreen;
        //mSplash.Location = mLocation;
        mSplash.TopMost = true;
        Application.Run(mSplash);
    }
}