Mike Turner
Mike Turner

Reputation: 471

stop a thread before closing form

Using .NET4, c#, I have a grid on a winform. When I hit a process button, I need to perform a timely operation with a few steps on each row and then update the row with a result. This way the user can see progress while the next row is processing. If the user hits cancel or closes the form, I need to finish the process for the current row and then break or close form. Based on my research, here is what I came up with. I'm left with 2 issues.

Here's my code:

delegate void OperateGridMethodDelegate();
delegate void UpdateProgressDelegate(int rowIndex, string msg);
bool isCancelled = false;


private void ButtonOne_Click(object sender, EventArgs e)
{
    isCancelled=false;
    OperateGridMethodDelegate delegate = new OperateGridMethodDelegate(LongProcess);`
    delegate.BeginInvoke(null,null);

}

private void ButtonTow_Click(object sender, EventArgs e)
{

    MyButtonOne.Enabled=false;
    isCancelled=true;

}

private void LongProcess()
{

    foreach (DataRow row in dataTableOne.Rows)
    {
        //Do Lengthy Process

        DisplayResult( rowIndex, "this is result of operation" );
        if(isCancelled)
        {
            MyButtonOne.Enabled=true;
            break;

        }

    }

}

private void DisplayResult(int rowIndex,string message)
{

    if(myGrid.InvokeRequired == false)
    {

        myGrid.Rows[rowIndex].value = message;

    }

    else
    {

        UpdateProgressDelegate delegate = new  UpdateProgressDelegate(DisplayResult);
        myGrid.BeginInvoke(delegate, new object[] { rowIndex, message });

    }

}

The 2 issues I'm left with are:

  1. When the form is closing, I want to wait for the LongProcess (that was called by my OperateGridMethodDelegate) to finish the row it's up to and then cancel (same way I did with ButtonTwo), but I can't get this to work.

  2. I notice a weird behavior when debugging and I'm not sure if this is a bug or correct, when a row is finished processing, the result does not get set. Instead, the next row is processed, and then the previous row result gets displayed. The second row result is displayed when the third row finishes etc. Then the last 2 row results get displayed basically at the same time.

Am I approaching this correctly?

Upvotes: 3

Views: 3401

Answers (1)

pay
pay

Reputation: 386

If you've launched some task in a thread, to wait for it to finish before proceeding you can do:

yourThread.Join();

This will block until the thread exits. You may want to use something like this in your Form_Closing event

Alternatively, if you want the thread to automatically terminate if the application is terminated, you need to set the background property of the thread:

yourThread.IsBackground = true;

This means it is a background thread of your main (UI) thread, so it will end with the main thread.

Edit:

Using your own thread:

private Thread yourThread = new Thread(() = > LongProcess());
yourThread.IsBackground = true;
yourThread.Start();  // This will begin your 'LongProcess' function.

Now if you want to block somewhere and wait for this to complete, you can do what I mentioned first: yourThread.Join();

Also note that if you set IsBackground = false and someone closes the application, that thread will not exit immediately, it will continue until it is complete despite the UI window being closed.

Upvotes: 3

Related Questions