Reputation: 93
I am unable to figure out the reason for this error:
Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
Here is my (stripped) code:
private: delegate void MyDelegate(Object^ openFileDialog1);
ListView^ myDelegate;
private: void import_links(Object^ openFileDialog1) {
myDelegate = (gcnew System::Windows::Forms::ListView());
myDelegate->BeginInvoke( gcnew MyDelegate( this, &Form1::import_links ), openFileDialog1);
//do some work here
}
private: System::Void Import_LinkClicked(System::Object^ sender, System::Windows::Forms::LinkLabelLinkClickedEventArgs^ e) {
OpenFileDialog^ openFileDialog1 = gcnew OpenFileDialog;
if ( openFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK )
{
Thread^ importThread = gcnew Thread(gcnew ParameterizedThreadStart(this,&Form1::import_links));
importThread->Start(openFileDialog1);
}
}
Please let me know the solution.
Upvotes: 0
Views: 2151
Reputation: 942000
myDelegate = (gcnew System::Windows::Forms::ListView());
Basic problems with this statement:
You already have a reference to an object that is owned by the correct thread. It is this
. So correct code would look like:
void import_links(Object^ openFileDialog1) {
if (this->InvokeRequired) {
this->BeginInvoke( gcnew MyDelegate( this, &Form1::import_links ), openFileDialog1);
}
else {
//do some work here
}
}
But do note the ultimate fallacy, you created a worker thread and the only thing it does is call this->BeginInvoke()
. That takes a fraction of a microsecond. Creating a thread to do so little work is never useful.
Refactor your code, use a BackgroundWorker. Let its DoWork event handler only do the kind of things that are expensive, like importing a file. Let its RunWorkerCompleted event only do the kind of things that need to happen on the UI thread, such as displaying the result of the import and hiding the "I'm working on it" notification.
Upvotes: 3