I have resolved the problem. After I change the invoke
call from
tComplete->Invoke(this, EventArgs::Empty);
to
Invoke(tComplete);
Everything works fine. What is the difference between
these calls?
Also if I start the worker thread from a control object,
I couldn't use Invoke(tComplete) call. If I do, I got a
'System.InvalidOperationException'
and the error message is
"The window handle must be established before you can
call Invoke and InvokeAsync". What's going on here?
Following is the complete test program using a control
object to start the worker thread.
----------------------------------------------------------
#pragma once
namespace TestForm4
{
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System:
ata;
using namespace System:
rawing;
using namespace System::Threading;
using namespace System:
iagnostics;
public __gc class Tobj : public Control
{
private: EventHandler *tComplete;
public: Tobj()
{
tComplete = new EventHandler(this,
&Tobj::tcomplete);
}
public: __event EventHandler *fcomplete;
/// <summary>
/// This method is called by the
/// background thread when it has finished
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private: void tcomplete(System::Object
*sender, System::EventArgs* e)
{
Debug::WriteLine("enter tcomplete");
fcomplete(sender, e);
}
public: System::Void dothread()
{
Debug::WriteLine(this, "enter dothread
this=");
Thread* tThread = new Thread(new
ThreadStart(this, tThreadProc));
tThread->Start();
}
private: System::Void tThreadProc()
{
// do web request here
// notify the work is complete
// The following call works
tComplete->Invoke(this,
EventArgs::Empty);
// The following call does not work ???
// It causes System.InvalidOperationException
//Invoke(tComplete);
}
};
/// <summary>
/// Form1 的摘要
/// </summary>
public __gc class Form1 : public
System::Windows::Forms::Form
{
private: Tobj *tobj;
public:
Form1(void)
{
this->tobj = new Tobj();
this->tobj->fcomplete += new
System::EventHandler(this, &Form1::rcomplete);
InitializeComponent();
}
protected:
void Dispose(Boolean disposing)
{
if (disposing && components)
{
components->Dispose();
}
__super:
ispose(disposing);
}
private: System::Windows::Forms::Button *
button1;
private:
/// <summary>
///
設計工具所需的&#
35722;數。
/// </summary>
System::ComponentModel::Container *
components;
/// <summary>
void InitializeComponent(void)
{
this->button1 = new
System::Windows::Forms::Button();
this->SuspendLayout();
//
// button1
//
this->button1->Location=System:
rawing:
oint
(40, 0);
this->button1->Name = S"button1";
this->button1->TabIndex = 0;
this->button1->Text = S"button1";
this->button1->Click += new
System::EventHandler(this, button1_Click);
//
// Form1
//
this->AutoScaleBaseSize =
System:
rawing::Size(5, 15);
this->ClientSize = System:
rawing::Size(292,
266);
this->Controls->Add(this->button1);
this->Name = S"Form1";
this->Text = S"Form1";
this->ResumeLayout(false);
}
private: System::Void button1_Click
(System::Object * sender, System::EventArgs * e)
{
tobj->dothread();
}
private: void rcomplete(System::Object *sender,
System::EventArgs* e)
{
Debug::WriteLine("enter rcomplete");
}
};
}
..