views:

38

answers:

3

I am loading a big treeview in a seperate thread. This thread starts at the load event of a form.

All goes well, until an error occurs in the load event. When an error occurs I close the form and the thread that loads my treeview must be aborted. But I don't know how to do this.

The problem is, that the form is closed and the thread is still working, so I get an InvalidOperationException. The program breaks down and this part of the thread is highlighted:

tvQuestionnaire.Invoke((MethodInvoker)delegate
{
    tvQuestionnaire.Nodes.Add(catNode);
});

The treeview on my form is called tvQuestionnaire. The whole function (which is called in my background worker) looks like this:

private void SetTreeviewData()
{
    // Get all categories
    List<Category> categories = _questionnaire.GetCategoriesFromQuestionnaire();

    // Get all questions which are retrieved by the question manager
    OrderedDictionary all_ordered_questions = _questionManager.AllQuestions;

    // Store all the questions in a List<T>
    List<Question> all_questions = new List<Question>();
    foreach (DictionaryEntry de in all_ordered_questions)
    {
        Question q = de.Value as Question;
        all_questions.Add(q);
    }

    foreach (Category category in categories)
    {
        // Create category node
        TreeNode catNode = new TreeNode();
        catNode.Text = category.Description;
        catNode.Tag = category;
        catNode.Name = category.Id.ToString();

        // Get all questions which belongs to the category
        List<Question> questions = all_questions.FindAll(q => q.CategoryId == category.Id);

        // Default set the font to bold (Windows issue)
        Font font = new Font(tvQuestionnaire.Font, FontStyle.Regular);

        foreach (Question question in questions)
        {
            // Create question node
            TreeNode queNode = new TreeNode();
            queNode.Text = question.Question;
            queNode.Tag = question;
            queNode.Name = "Q" + question.Id;
            queNode.NodeFont = font;

            // Determine which treenode icon to show
            SetTreeNodeIcon(ref queNode, question);

            // Add node to category node
            catNode.Nodes.Add(queNode);
        }

        if (_closing)
            return;

        // Add category node to treeview
        tvQuestionnaire.Invoke((MethodInvoker)delegate
        {
            tvQuestionnaire.Nodes.Add(catNode);

            // Now the category (and thus the questions) are added to treeview
            // Set questions treenode icon
            //SetTreeNodeIcon(questions);
        });
    }

    // Set each category under its parent
    for (int i = tvQuestionnaire.Nodes.Count - 1; i >= 0; i--)
    {
        Category category = tvQuestionnaire.Nodes[i].Tag as Category;
        TreeNode node = tvQuestionnaire.Nodes[i];

        if (IsWindow(this.Handle.ToInt32()) == 0)
            return;

        tvQuestionnaire.Invoke((MethodInvoker)delegate 
        {
            if (category.ParentId == null)
                return;
            else
            {
                // Find parent node
                TreeNode[] parentNodes = tvQuestionnaire.Nodes.Find(category.ParentId.ToString(), true);

                //Remove current node from treeview
                tvQuestionnaire.Nodes.Remove(node);
                parentNodes[0].Nodes.Insert(0, node);
            }
        });
    }
}

This is the only method that my background worker calls.

So my question is, how can I prevent that the Exception occurs? How do I check the form where the treeview is on, is still 'alive'?

A: 

Why not catch this event, than abort the thread's execution?

rursw1
+2  A: 

One solution would be to call the CancelAsync method of the backgroundworker (BGW) when you need to close the form. In the DoWork event handler, check at the beginning of the loop that cancellation has not been requested. If it was, exit the loop (and the DoWork handler). In the form, wait for the BGW to complete (either success or cancellation)

Johann Blais
A: 

Check IsHandleCreated property of a form. If the form is still alive, it will true.

Dmitry Karpezo