14 Replies - 2392 Views - Last Post: 11 June 2011 - 08:29 AM Rate Topic: -----

#1 skybomb0  Icon User is offline

  • D.I.C Head

Reputation: 10
  • View blog
  • Posts: 92
  • Joined: 12-May 10

Split Processing Time Between Form and Function

Posted 05 June 2011 - 10:43 PM

I am making a Sudoku Solver to practice recursion (brute force solver). I have the solver working perfectly. Now I am working on the GUI part. I want to show the process by slowing down the calculation process and showing it on the GUI in real time.

In the Solve function of my static SudokuSolver class, I pass a Grid object which is basically just a 2d array, one spot for each cell in the sudoku puzzle. When this Grid object changes, it fires an event telling me that one of the numbers changed. In the event handler, I update the form. This all works great.

But this makes the changes go by at light speed and I want to slow it down. So, obviously you can't put in a Thread.Sleep call in the event handler because that would stop the form from responding. And even while the Grid is changing at full speed, the form is still not responding to my clicks because it is stuck processing the answer to the problem.

How do I split the time between processing the solution and still keep the form responsive?

Is putting the processing on a separate thread the only way? And if so, how do I update the form from another thread?


Indexer in Grid class which fires the OnGridItemChanged event.
public int this[int row,int col]
{
    get
    {
        return grid[row, col];
    }
    set
    {
        if (value != grid[row, col])
        {
            grid[row, col] = value;
            OnGridItemChanged(new GridItemChangedEventArgs(row, col));
        }
    }
}



Event handler attached to GridItemChanged event. This is in the MainForm class.
private void grid_GridItemChanged(object sender, GridItemChangedEventArgs e)
{
    if (grid[e.Row, e.Col] == 0)
        textboxGrid[e.Row, e.Col].Text = "";
    else
        textboxGrid[e.Row, e.Col].Text = grid[e.Row, e.Col].ToString();

    this.Update();
}



Is This A Good Question/Topic? 0
  • +

Replies To: Split Processing Time Between Form and Function

#2 eclipsed4utoo  Icon User is offline

  • Not Your Ordinary Programmer
  • member icon

Reputation: 1524
  • View blog
  • Posts: 5,957
  • Joined: 21-March 08

Re: Split Processing Time Between Form and Function

Posted 06 June 2011 - 05:33 AM

You don't "split the time", you do the solving on a background thread. This will keep the UI responsive and allow you to call Thread.Sleep in the background thread.

Remember, you can't access UI controls from a background thread. You will need to call the Invoke/BeginInvoke method of the control you are trying to update to allow it to update from the background thread.
Was This Post Helpful? 0
  • +
  • -

#3 skybomb0  Icon User is offline

  • D.I.C Head

Reputation: 10
  • View blog
  • Posts: 92
  • Joined: 12-May 10

Re: Split Processing Time Between Form and Function

Posted 06 June 2011 - 12:18 PM

That's what I was thinking. I will have to reorganize my Solver class, but that should be it. Thank you for your response.
Was This Post Helpful? 0
  • +
  • -

#4 Curtis Rutland  Icon User is online

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 4312
  • View blog
  • Posts: 7,467
  • Joined: 08-June 10

Re: Split Processing Time Between Form and Function

Posted 06 June 2011 - 12:28 PM

I've personally fallen in love with Tasks. If you're using .NET 4.0, they're probably what you should use instead of Threads or BackgroundWorkers. It makes it much simpler, and using Continuations and TaskSchedulers, you don't even have to use Invoke.

Read this:

http://www.dreaminco...ction-to-tasks/

It's a great tutorial on tasks.
Was This Post Helpful? 2
  • +
  • -

#5 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon


Reputation: 2216
  • View blog
  • Posts: 9,352
  • Joined: 29-May 08

Re: Split Processing Time Between Form and Function

Posted 06 June 2011 - 12:33 PM

Also consider using an Event which indicate that the grid as changed, so that your solver class is independent of the GUI
Was This Post Helpful? 1
  • +
  • -

#6 skybomb0  Icon User is offline

  • D.I.C Head

Reputation: 10
  • View blog
  • Posts: 92
  • Joined: 12-May 10

Re: Split Processing Time Between Form and Function

Posted 06 June 2011 - 07:46 PM

@adam

Yeah, that's what I have done. So far it has worked out great.

@Curtis

That looks interesting. I have never like managing threads because they can get very confusing when you have more than one thread, especially when you have to have threads that interact with each other. I'll take a look at tasks.
Was This Post Helpful? 0
  • +
  • -

#7 skybomb0  Icon User is offline

  • D.I.C Head

Reputation: 10
  • View blog
  • Posts: 92
  • Joined: 12-May 10

Re: Split Processing Time Between Form and Function

Posted 06 June 2011 - 07:59 PM

@Curtis

Those tasks are great. Basically, it does everything I would normally attempt to do with a thread, but it does it for me! I will have to brush up on my syntax, but thanks. I wouldn't have found this myself. I'm still stuck in 3.5 world.

This post has been edited by skybomb0: 06 June 2011 - 08:07 PM

Was This Post Helpful? 0
  • +
  • -

#8 eclipsed4utoo  Icon User is offline

  • Not Your Ordinary Programmer
  • member icon

Reputation: 1524
  • View blog
  • Posts: 5,957
  • Joined: 21-March 08

Re: Split Processing Time Between Form and Function

Posted 07 June 2011 - 04:45 AM

View Postskybomb0, on 06 June 2011 - 10:59 PM, said:

@Curtis

Those tasks are great. Basically, it does everything I would normally attempt to do with a thread, but it does it for me! I will have to brush up on my syntax, but thanks. I wouldn't have found this myself. I'm still stuck in 3.5 world.


If you are stuck in the .Net 3.5 world and can't use Tasks, you can still use the BackgroundWorker. It will also handle threading for you. Very simple to use.

We have a tutorial here that should help you out.
Was This Post Helpful? 0
  • +
  • -

#9 skybomb0  Icon User is offline

  • D.I.C Head

Reputation: 10
  • View blog
  • Posts: 92
  • Joined: 12-May 10

Re: Split Processing Time Between Form and Function

Posted 07 June 2011 - 08:57 AM

An update should do the trick.
Was This Post Helpful? 0
  • +
  • -

#10 skybomb0  Icon User is offline

  • D.I.C Head

Reputation: 10
  • View blog
  • Posts: 92
  • Joined: 12-May 10

Re: Split Processing Time Between Form and Function

Posted 11 June 2011 - 01:28 AM

@Curtis

I do believe I have fallen in love with Tasks also. But not in this case. From what I have found googling, there is no built in way to provide progress updates during the task. Correct me if I am wrong, but I think I need to stick with the old dirty way of threading.
Was This Post Helpful? 0
  • +
  • -

#11 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon


Reputation: 2216
  • View blog
  • Posts: 9,352
  • Joined: 29-May 08

Re: Split Processing Time Between Form and Function

Posted 11 June 2011 - 01:57 AM

It is possible. Post the code you're currently having trouble with.
Was This Post Helpful? 0
  • +
  • -

#12 skybomb0  Icon User is offline

  • D.I.C Head

Reputation: 10
  • View blog
  • Posts: 92
  • Joined: 12-May 10

Re: Split Processing Time Between Form and Function

Posted 11 June 2011 - 02:44 AM

Duh. As I was writing a response to the previous post describing my situation, I begin to write "but the new task is not blocking". Really? Common sense tells me that is where I should use a method call, not a task. Anyways, I got the code to work after using common sense. Here is the code in case anyone is interested.

private void Solve_Click(object sender, EventArgs e)
{
    Solver s = new Solver(puzzle);
    Solver.ProgressCallback callback = new Solver.ProgressCallback(OnGridChanged);

    Task.Factory.StartNew<bool>(
        () => s.Solve(callback))
        .ContinueWith((i) => OnSolutionComplete());
}

private void OnSolutionComplete()
{
    MessageBox.Show("Solution Complete");
}

private void OnGridChanged(GridItemChangedEventArgs e)
{
    if (textboxGrid[e.Row, e.Col].InvokeRequired)
    {
        Invoke(new Solver.ProgressCallback(OnGridChanged), new object[] { new GridItemChangedEventArgs(e.Row, e.Col, e.NewValue) });
    }

    if (e.NewValue == 0)
        textboxGrid[e.Row, e.Col].Text = "";
    else
        textboxGrid[e.Row, e.Col].Text = e.NewValue.ToString();
}



public delegate void ProgressCallback(GridItemChangedEventArgs e);
public bool Solve(ProgressCallback callback)
{
    Puzzle.Cell nextCell = puzzle.FindNextEmptyCell();
    if (nextCell.Equals(new Puzzle.Cell(-1, -1)))
    {
        return true;
    }

    for (int n = 1; n <= puzzle.Size; n++)
    {
        if (puzzle.IsValid(n, nextCell.Row, nextCell.Col))
        {
            puzzle[nextCell.Row, nextCell.Col] = n;
            callback(new GridItemChangedEventArgs(nextCell.Row, nextCell.Col, n));
                    
            if (Solve(callback))
                return true;

            puzzle[nextCell.Row, nextCell.Col] = 0;
            callback(new GridItemChangedEventArgs(nextCell.Row, nextCell.Col, 0));
        }
    }

    return false;
}


Was This Post Helpful? 0
  • +
  • -

#13 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon


Reputation: 2216
  • View blog
  • Posts: 9,352
  • Joined: 29-May 08

Re: Split Processing Time Between Form and Function

Posted 11 June 2011 - 06:04 AM

Have a look the example in my Blog. Tasks + Events + RX Schedulers = Concurrency Heaven
Was This Post Helpful? 0
  • +
  • -

#14 Sergio Tapia  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1251
  • View blog
  • Posts: 4,168
  • Joined: 27-January 10

Re: Split Processing Time Between Form and Function

Posted 11 June 2011 - 06:59 AM

Just wanted to say that I never really liked BackgroundWorkers and threads before, with Tasks I really enjoy making heavy duty processes and keeping the GUI running silky smooth. It's fantastic. :)
Was This Post Helpful? 0
  • +
  • -

#15 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon


Reputation: 2216
  • View blog
  • Posts: 9,352
  • Joined: 29-May 08

Re: Split Processing Time Between Form and Function

Posted 11 June 2011 - 08:29 AM

skybomb0 I've written a Solver that uses a Task, along with RX to to the updating of a form.
30 LoC for GUI and Task Setup
400 LoC for the Solver classes & objects.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1