1

I am trying to show some loading screen while my work is in progress. My work is justto move one file at a time from one cell to another cell, the code is working perfectly. Butwhen i am trying to move a group of files the loading screen is coming and after job its stuck for 20-30 seconds

i found the solution: its because after all the files are moved to the next column, my control is going to dataGridView1_DataBindingComplete so whats happening is the grid-cell is giving color based on my condition when i removed the dataGridView1_DataBindingComplete its working prerfectly.. But i need to give color too.. please tell me how can i deal with this situation.

Codes:

    private void button3_Click(object sender, EventArgs e)
    {
        Hide();
        bool done = false;
        ThreadPool.QueueUserWorkItem((x) =>
        {
            using (var splashForm = new Form4())
            {
                splashForm.Show();
                while (!done)
                    Application.DoEvents();
                splashForm.Close();
            }
        });

        move(); // this is my function to move all files from one column to another
        done = true;
        Show();

    }

           private void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
    {
        string strVal = ini.ReadValue("Action", "Doc-Controller");

        bool authenticated = true;
        string textboxGroupName1 = ini.ReadValue("Action", "Fabricator");
        if (authenticated == UserInCustomRole(textboxGroupName1))
        {

            foreach (DataGridViewRow row in dataGridView1.Rows)
            {
                string fName1 = System.IO.Path.GetFileNameWithoutExtension(row.Cells[2].Value.ToString());
                string fName2 = System.IO.Path.GetFileNameWithoutExtension(row.Cells[3].Value.ToString());
                if (!string.IsNullOrEmpty(fName1) && !string.IsNullOrEmpty(fName2))
                {
                    var f1 = GetValue(fName1.ToCharArray()[fName1.Length - 2]) * 16 + GetValue(fName1.ToCharArray()[fName1.Length - 1]);
                    var f2 = GetValue(fName2.ToCharArray()[fName2.Length - 2]) * 16 + GetValue(fName2.ToCharArray()[fName2.Length - 1]);
                    //if (System.IO.Path.GetFileName(fName1) != System.IO.Path.GetFileName(fName2))
                    if (f1 > f2)
                    {
                        //MessageBox.Show(fName1);
                        DataGridViewCellStyle style = new DataGridViewCellStyle();
                        style.BackColor = Color.Yellow;
                        row.Cells[2].Style = style;
                    }
                    else if (f2 > f1)
                    {
                        //MessageBox.Show(fName1);
                        DataGridViewCellStyle style = new DataGridViewCellStyle();
                        style.BackColor = Color.Yellow;
                        row.Cells[3].Style = style;
                    }

                    if (f1 == f2)
                    {
                        DataGridViewCellStyle style = new DataGridViewCellStyle();
                        style.BackColor = Color.Plum;
                        row.Cells[3].Style = style;
                        row.Cells[2].Style = style;
                    }
                }
            }

        }

        if (authenticated == UserInCustomRole(strVal))
        {
            foreach (DataGridViewRow row in dataGridView1.Rows)
            {
                string fName1 = System.IO.Path.GetFileNameWithoutExtension(row.Cells[3].Value.ToString());
                string fName2 = System.IO.Path.GetFileNameWithoutExtension(row.Cells[4].Value.ToString());
                if (!string.IsNullOrEmpty(fName1) && !string.IsNullOrEmpty(fName2))
                {
                    var f1 = GetValue(fName1.ToCharArray()[fName1.Length - 2]) * 16 + GetValue(fName1.ToCharArray()[fName1.Length - 1]);
                    var f2 = GetValue(fName2.ToCharArray()[fName2.Length - 2]) * 16 + GetValue(fName2.ToCharArray()[fName2.Length - 1]);
                    //if (System.IO.Path.GetFileName(fName1) != System.IO.Path.GetFileName(fName2))
                    if (f1 > f2)
                    {
                        //MessageBox.Show(fName1);
                        DataGridViewCellStyle style = new DataGridViewCellStyle();
                        style.BackColor = Color.Yellow;
                        row.Cells[3].Style = style;
                    }
                    else if (f2 > f1)
                    {
                        //MessageBox.Show(fName1);
                        DataGridViewCellStyle style = new DataGridViewCellStyle();
                        style.BackColor = Color.Yellow;
                        row.Cells[4].Style = style;
                    }

                    if (f1 == f2)
                    {
                        DataGridViewCellStyle style = new DataGridViewCellStyle();
                        style.BackColor = Color.Plum;
                        row.Cells[4].Style = style;
                        row.Cells[3].Style = style;
                    }
                }
            }
        }
    }

    private int GetValue(char ch)
    {
        if (ch >= 48 && ch <= 57)
            return ch - 48;
        else if (ch >= 65 && ch <= 90)
            return ch - 65 + 10;
        else
            return 0;
    }
  • 1
    Put the **WORK** in another thread, not the dialog. Build up a list of the work to be done and pass that to a BackgroundWorker so the work will be done in another thread. Close your dialog in the RunWorkerCompleted() event... – Idle_Mind Dec 09 '14 at 17:28
  • 1
    You didn't actually do any of the **WORK** inside the DoWork() handler! When you call `movement()` directly from the button3 click handler like that, all of that code runs in the main UI thread. This is why your form is getting "stuck". The work inside `movement()` needs to be called from within the DoWork() handler. **BUT** you shouldn't be reading directly from your UI components from within there. This is why I said you need to build a list of your work to be done and **pass** that into RunWorkerAsync(). – Idle_Mind Dec 09 '14 at 18:55
  • 1
    Also, the "loading" dialog shouldn't be running in a different thread either. Just display it directly from the button3 click handler before starting the BackgroundWorker() that does the work. There are **TONS** of examples in MSDN, here on SO, and out on the web that demonstrate how to use the BackgroundWorker(). Go read some of them... – Idle_Mind Dec 09 '14 at 18:57
  • @Idle_Mind so how can i know.. to give my `backgroundWorker2.CancelAsync();` i just modified as you said . and my `backgroundWorker2.RunWorkerAsync();` and `backgroundWorker2.CancelAsync();` is coming one instruction after other.. –  Dec 09 '14 at 19:08
  • @Idle_Mind i can literally see my gird is flickering... –  Dec 09 '14 at 19:11
  • @Idle_Mind and after certain number of flickers my message "test" is coming... what could be the reason –  Dec 09 '14 at 19:11
  • Despite having a C# tag, there isn't much discussion going on in this thread. Why could this be? Simply put, because the code is a complete mess and the whole thing needs to be **re-designed** to work properly. This isn't a "change a couple of things" kinda problem, and I'm guessing people don't want to put in the effort required to walk you through what is a complex task given what you're starting with. Sorry. – Idle_Mind Dec 09 '14 at 20:19
  • 1
    Stacy refactor your code to close the form if you are doing multi-threaded have you looked at this code here the only thing that I cringe about is the part in the working example about `Application.DoEvents()` anyway here ya go http://stackoverflow.com/questions/48916/multi-threaded-splash-screen-in-c || this project http://www.codeproject.com/Articles/5454/A-Pretty-Good-Splash-Screen-in-C – MethodMan Dec 09 '14 at 22:01
  • @DJKRAZE did you checked my project.. i have emailed u –  Dec 11 '14 at 18:11
  • I cringe saying this, but since you refuse to do it the right way, simply put `Application.DoEvents();` inside the two `foreach` loops of your DataBindingComplete() event. – Idle_Mind Dec 11 '14 at 21:13
  • @Idle_Mind yup i guess we are closer.. when i gave `Application.DoEvents();` inside the two `foreach` loops of my `DataBindingComplete()` event. an error occued: `An exception of type 'System.NullReferenceException' occurred in MovedFiles.exe but was not handled in user code Additional information: Object reference not set to an instance of an object. If there is a handler for this exception, the program may be safely continued.` –  Dec 11 '14 at 21:34

2 Answers2

0

In an effore to help you see the big picture, here is an overview of one way to approach the problem. This only uses ONE BackgroundWorker, and note that the dialog is being displayed by the main UI thread since it is displayed from the ProgressChanged() event:

Button Click Handler
    Disable the Button
    Build a List of the Work to be done
    Pass List to RunWorkerAsync

DoWork Handler
    Cast e.Argument back to your List
    Call ReportProgress() with -1 as the param
    Iterate over the List and Do the Work
        ...after you move each file...
        Call ReportProgress() and pass the percentage complete as the first parameter,
            with the data to update the grid with in the second parameter
            *You can pass anything you want out in the second parameter, like a Custom Class

ProgressChanged Handler
    If e.ProgressPercent is -1 Then
        Display your Dialog
    Else
        Cast e.UserState to your progress structure and update the grid accordingly

RunWorkerCompleted Handler
    Close your dialog
    Re-enable the Button
Idle_Mind
  • 38,363
  • 3
  • 29
  • 40
  • i found the answer.. its becasue after all the files are moved to the next column `the control is going to dataGridView1_DataBindingComplete` so whats happening is the grid-cell is giving color based on my condition when i removed the dataGridView1_DataBindingComplete its working perfectly.. But i need to give color too.. please tell me how can i deal with this situation.. please see my updated codes –  Dec 11 '14 at 19:25
  • `Application.DoEvents();` is taken from WPF –  Dec 12 '14 at 16:39
-1

You can't close a Thread when one of his child is Alive. For our case, it's your Form4.

Try to put the IsBackGround at true. It will allow your Thread to die even if one of his child is alive:

private void button3_Click(object sender, EventArgs e)
{
    Thread thd = new Thread(new ThreadStart(SomeThread));
    thd.IsBackground = true;
    thd.Start();
    movement();
    dataGridView1.Refresh();
    thd.Abort();
}
  • 2
    While this will technically work, it is the completely wrong approach to the problem at hand. – Idle_Mind Dec 09 '14 at 17:30
  • @Idle_Mind any other ways.. i approached using background worker and t worked.. but the thing is after moving a large number of files.. my form is stuck for may be 20-30 sec and comes back to normal state.. `but there is no problem while i am moving one file`.. What could be the reason.. Please find my edited codes –  Dec 09 '14 at 18:43