سؤال

I have a main form that runs a BackgroundWorker thread. While the worker is running I "freeze" the main form and wait for it to finish while showing its progress.

In one on the scenarios the worker can display an OpenFileDialog for the user to select a file. I use a third thread to run the OpenFileDialog and set it's ApartmentState to STA because the OpenFileDialog demands it (throws exception if I don't do it) and the worker ApartmentState is MTA.

The problem is that I want to pass to the OpenFileDialog thread the main form as a parameter so it can be used when calling OpenFileDialog.ShowDialog. Something like this:

public void ThreadProcShowDialog(object param)
{
    Form parent = (Form)param;
    dialog.ShowDialog(parent);
}

Of course, ShowDialog throws:

Cross-thread operation not valid: Control 'Form' accessed from a thread other than the thread it was created on.

How can I do this in a thread safe manner?

The object of this is that the OpenFileDialog will run in a STA thread while blocking the main form from displaying over it (block the user from clicking the form below thus hiding the OpenFileDialog).

Thanks

هل كانت مفيدة؟

المحلول

Found it!

A fellow programmer working with me suggested a simple solution that actually worked. Instead of running the OpenFileDialog on a third thread just run it on the main form (the one that started the worker thread.

It looks like this:

//Code inside worker method
OpenFileDialog dialog= new OpenFileDialog();
DialogResult result = DialogResult.None;

Invoke(new MethodInvoker(delegate() { result = dialog.ShowDialog(this); }));
if (result == DialogResult.OK)
{
    ...
}

This way I block the main form from being clicked and the OpenFileDialog runs in a STA thread.

And to think the one that solved it is a C++ programmer. ;-)

I hope this will be helpful to someone...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top