0

I have made a WPF application which has a button to move some files attached to the column cells from one column to another column. The moment when I press the button it shows a nice animation and moves all files to the next column's cells.

But my real problem is once I give my function color_check(), my application is getting stuck. I really don't know why. Is there any help I can get out for this?

Code:

 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(); //file moving function
        //color_check();  if i give this fn, my form stucks and comes to live after 10 - 20 sec
        done = true;
        MessageBox.Show("TEST FINISHED");
        Show();
    }

 public void color_check()  //this is my problem making fn
    {
        dataGridView1.Refresh();
         string strVal = ini.ReadValue("Action", "Doc-Controller");

        bool authenticated = true;

        if (authenticated == UserInCustomRole(strVal))
        {
            foreach (DataGridViewRow row in dataGridView1.Rows)
            {
                // Application.DoEvents(); 
                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;
                    }
                }
            }

    }
Andrew Barber
  • 39,603
  • 20
  • 94
  • 123
  • 1
    Have you tried asynchronous? – Patrick Dec 12 '14 at 18:20
  • @Patrick what is that?? –  Dec 12 '14 at 18:22
  • 5
    When you have to work with GUI you usually stuck your program because the UI Thread is handling other stuff so you have to make some methods async in order to make those operations liberate the GUI Thread have a look at [link](http://stackoverflow.com/questions/14177891/can-somebody-please-explain-async-await) [link](http://stackoverflow.com/questions/10960998/how-different-async-programming-is-from-threads) – Patrick Dec 12 '14 at 18:26
  • use a `BackgroundWorker` thread for the `color_check()` method? – Saggio Dec 12 '14 at 18:38
  • @Saggio i already did background and same thing with that too –  Dec 12 '14 at 18:47
  • @Patrick i found `Task task1 = Task1(); Task task2 = Task2();` interesting.. can i give my `move() and color_check()` instead of `Task1(); & Task2();` –  Dec 12 '14 at 18:50
  • 1
    try or delegating your `color_check` to a task and run it or make it async, but remember that if you have to change something in the GUI you will have to Invoke the controls you wanna change – Patrick Dec 12 '14 at 19:18

2 Answers2

2

The issue is that your code which is invoked on button3_click() is blocking the UI thread. That's why it appears to freeze for a while - the code is executing, and once it's complete the UI thread becomes responsive again.

The way to resolve this is to perform your actions asynchronously on another thread. In .NET 4 and beyond, you can use Tasks and the async/await keywords to help you manage this. If you are working on a version older than .NET 4, then you'll want to take a look at BackgroundWorker or other threading options compatible with your version of .NET.

Note that if you want to modify the GUI in your async method, you may need to use a Dispatcher.Invoke() to do so safely.

Here are some links to help you understand some approaches available to you

C# Blog on Understanding a simple async program

MSDN reference for async/await

Related StackOverflow question on how to use BackgroundWorkers

Related StackOverflow question on how to access the UI thread directly

Community
  • 1
  • 1
Ben Giles
  • 21
  • 3
  • now when i changed my `color_check()` function to `private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)` its working fine.. evry thing is fine.. but it takes lto of time.. to the entire job/. but the processing is happening too slow.. any way to increase its speed. –  Dec 15 '14 at 21:19
1

In a normal UI application, no 2 functions that work on the GUI will run at the same time. This would result in a lot of issues otherwise, which usually would cause the program to crash. For example there could be 2 functions running at the same time that each check if the same list has at least one element and then remove an element - because they run at the same time they first both check if the list has 1 element.

That's why GUI functions all run in the same thread, meaning they run only one at a time. While color_check runs, other functions don't run.

You can launch additional threads and do work on them that is executed in parallel, of you can speed up the color_check function, for example by breaking it up into parts which run at lower priority one at a time, using a dispatcher

Take this:

public void color_check()  //this is my problem making fn
{
    dataGridView1.Refresh();
    string strVal = ini.ReadValue("Action", "Doc-Controller");

    bool authenticated = true;

    if (authenticated == UserInCustomRole(strVal))
    {
        foreach (DataGridViewRow row in dataGridView1.Rows)
        {
           ProcessRow(row);
        }
    }
}

and change it to this:

public void color_check()  //this is my problem making fn
{
    dataGridView1.Refresh();
    string strVal = ini.ReadValue("Action", "Doc-Controller");

    bool authenticated = true;

    if (authenticated == UserInCustomRole(strVal))
    {
        foreach (DataGridViewRow row in dataGridView1.Rows)
        {
           Dispatcher.BeginInvoke(DispatcherPriority.Background, ()=>{Process(row);});
        }
    }
}

In this code, Dispatcher.BeginInvoke tells the UI thread that it should run Process(row), as soon as it finds the time. This might result in 200 Process(row) calls that are waiting to be executed. It's still all executed on the UI thread and only one thing at a time. If a mouse click happens after the first hundred have been completed, the GUI thread will first finish number onehunderd and one, and then handle the mouseclick, before picking up the remaining calls to process.

There's a disadvantage to this approach. By allowing other functions to be executed in between different calls to Process(row), you may get surprising results. Especially if these other processes also change the cell styles.

Peter
  • 5,608
  • 1
  • 24
  • 43
  • ,, what do you mean by `ProcessRow(row);`!!!!. i don't have anything lie that in my fn. also when i gave this fn.. it is showing errors in `Dispatcher` then `DispatcherPriority` and `Process`.. please let me know.. –  Dec 13 '14 at 03:07
  • It's an abstraction. Refactor your code so that all that stuff that you do in the for loop is done by a function instead, and your current code will look exactly the same as the first code sample I gave. – Peter Dec 14 '14 at 23:08
  • when i changed my color_check() to `private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)` its working fine.. but the processing is happening too slow.. any way to increase its speed. –  Dec 15 '14 at 21:18