creating a form in a new thread

  • Thread starter Thread starter dk60
  • Start date Start date
D

dk60

Here is a problem I encountered concerning threads:
Here is the code in Form1 button click handler:

AddForm addForm = new AddForm(booksDataSet.Titles);
Thread addTitleThread=new Thread(new
ThreadStart(addForm.GetNewTitle));
addTitleThread.Start();

Here is the code in AddForm:

public AddForm(BooksDataSet.TitlesDataTable titlesTable)
{
InitializeComponent();
titles = titlesTable;
randomSleepTime = new Random();
}

private void AddButton_Click(object sender, EventArgs e)
{
lock(titles)
{
Thread.Sleep(randomSleepTime.Next(1, 3001));
titles.Rows.Add(Int32.Parse(ISBNTextBox.Text),
TitleTextBox.Text,
Int32.Parse(EditionTextBox.Text),
Int32.Parse(CopyrightTextBox.Text));
}
}

internal void GetNewTitle()
{
this.ShowDialog();
}

As long the second form (addForm) remains open, Form1 behaves just
fine, but after closing the second form, the dataGridView in Form1
misbehaves (no scroll bar, no refresh and so on)
What did I do wrong?
Thanks
 
[...]
As long the second form (addForm) remains open, Form1 behaves just
fine, but after closing the second form, the dataGridView in Form1
misbehaves (no scroll bar, no refresh and so on)
What did I do wrong?

Looks to me like the main thing you did wrong was use a thread to display
the second form. That's not a good practice, even though it can be done
if you're careful. Subsequently however, the other thing you did wrong
was modify the table contained in the first form from the second thread.
This is a decidedly illegal operation and if you were using VS 2005, you
would have gotten an "illegal cross-thread call" MDA exception.

There's really no reason for you to use a second thread here at all. If
you don't want the second form to be modal, just use the Show() method
instead of the ShowDialog() method. If you do want it to be modal (that
is, block access to the first form), then just call ShowDialog() as you're
doing here, but do it where you currently create a new thread (*instead
of* creating a new thread).

Pete
 
Thanks,
first, I am using VS 2005 and didn't get an error. The thing is that I
want to be able to open a few "second" forms, each one modifying the
database. Would using Invoke help?

Peter Duniho :
[...]
As long the second form (addForm) remains open, Form1 behaves just
fine, but after closing the second form, the dataGridView in Form1
misbehaves (no scroll bar, no refresh and so on)
What did I do wrong?

Looks to me like the main thing you did wrong was use a thread to display
the second form. That's not a good practice, even though it can be done
if you're careful. Subsequently however, the other thing you did wrong
was modify the table contained in the first form from the second thread.
This is a decidedly illegal operation and if you were using VS 2005, you
would have gotten an "illegal cross-thread call" MDA exception.

There's really no reason for you to use a second thread here at all. If
you don't want the second form to be modal, just use the Show() method
instead of the ShowDialog() method. If you do want it to be modal (that
is, block access to the first form), then just call ShowDialog() as you're
doing here, but do it where you currently create a new thread (*instead
of* creating a new thread).

Pete
 
Thanks,
first, I am using VS 2005 and didn't get an error.

Hmmm...well, maybe I misunderstand how the ShowDialog() method works. I
would research it more, but for some reason MSDN's web site isn't working
well right now. I expected that it would start its own message pump on
the thread on which you call ShowDialog(), but maybe it somehow simply
configures the message pump on the form's creating thread to do the work
(possibly calling Invoke() implicitly? I'm not sure).

Anyway, the bottom line is that there's something fishy about the code you
posted. I certainly wouldn't write the code that way, nor do I see any
reason to.
The thing is that I
want to be able to open a few "second" forms, each one modifying the
database. Would using Invoke help?

I don't see why needing "a few 'second' forms" is cause for creating new
threads. You can create as many forms as you like. If you want more than
one to be active at once, then they need to be modeless, shown with the
Show() method rather than the ShowDialog() method. And if you want them
to all be active but the user to not be able to interact with the primary
form, then you'll need to disable the primary form yourself. But there's
no fundamental reason to create multiple threads, nor do I think it's a
safe approach.

You could try using Invoke(), but if you're using VS 2005 and are sure
that the cross-thread call MDA check is enabled, and you're not seeing the
MDA exception, then I don't see what using Invoke() would solve. If it
does fix the problem, then it means that you've somehow figured out a way
to make a GUI cross-thread call without the MDA noticing. :)

For sure, you should use Invoke() (or BeginInvoke()) any time you are
trying to call into methods on a Control instance from a thread other than
the thread on which that Control was created. But according to you,
that's not happening here.

Pete
 
Thanks a lot.
Just two more things:
1. how do I enable the cross-thread call MDA check?
2. In this case I thought Invoke() could help, since making changes to
the dataset causes changes to the datagridview, which was created in
the GUI thread. Am I wrong?
Thanks.


Peter Duniho :
 
Thanks a lot.
Just two more things:
1. how do I enable the cross-thread call MDA check?

The MDA exceptions can be enabled or disabled in the VS
"Debug/Exceptions..." dialog (under the "Managed Debugging Assistants"
section). My guess is that since you need to ask, it's already enabled,
since it should be enabled by default. However, I can't explain why the
exception doesn't happen when you attempt to access a form from the wrong
thread.
2. In this case I thought Invoke() could help, since making changes to
the dataset causes changes to the datagridview, which was created in
the GUI thread. Am I wrong?

Well, that's just it. If you aren't getting the cross-thread exception,
and you haven't turned the that MDA exception off, then that suggests that
somehow your code is still running all on the same thread, in spite of the
fact that you call ShowDialog() on a different thread. Why that should
be, I have no idea.

I just put together a quick test application that does basically what your
code does: a main form with a button that starts a new thread that creates
a new form and calls ShowDialog() on that form. Each form winds up
running in its own thread. In addition, I've confirmed that trying to
access a control on the main form results in the cross-thread exception.

For what it's worth, it would be a lot simpler to offer advice if you were
able to provide a concise-but-complete sample of code that shows the
problem you're having. There are some seemingly contradictory things
about your problem description that could be cleared up easily with a
short sample program that illustrates the problem.

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top