Help again the second time around - Asynccallback runtime error (C++)

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
Hi guys,<br/>
<br/>
I am having a runtime error everytime it passes to this statement.<br/>
<br/>
m_mainSocket->BeginAccept(gcnew AsyncCallback(this, &CServerApp::Form1::OnClientConnect), nullptr);<br/>
<br/>
The source code and detailed exception details are provided below. Thanks in advance guys.<br/>
<br/>
Here is the detailed information regarding the exception<br/>
<br/>
<br/>
System.Reflection.TargetParameterCountException was unhandled<br/>
Message=Parameter count mismatch.<br/>
Source=mscorlib<br/>
StackTrace:<br/>
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)<br/>
at System.Delegate.DynamicInvokeImpl(Object[] args)<br/>
at System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry tme)<br/>
at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)<br/>
at System.Threading.ExecutionContext.runTryCode(Object userData)<br/>
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)<br/>
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)<br/>
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)<br/>
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)<br/>
at System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme)<br/>
at System.Windows.Forms.Control.InvokeMarshaledCallbacks()<br/>
at System.Windows.Forms.Control.WndProc(Message& m)<br/>
at System.Windows.Forms.DataGridView.WndProc(Message& m)<br/>
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)<br/>
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)<br/>
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)<br/>
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)<br/>
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)<br/>
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)<br/>
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)<br/>
at System.Windows.Forms.Application.Run(Form mainForm)<br/>
at main(String[] args) in d:projectscentralized monitoring serverphase 1.5 c++cserverappcserverappcserverapp.cpp:line 16<br/>
InnerException:<br/>
<br/>
here is the source code (the staement where the exception occurs is underlined and bold):<br/>
<br/>
#pragma once<br/>
#include "Client.h"<br/>
#include "SocketPacket.h"<br/>
<br/>
namespace CServerApp {<br/>
<br/>
using namespace System;<br/>
using namespace System::ComponentModel;<br/>
using namespace System::Collections;<br/>
using namespace System::Windows::Forms;<br/>
using namespace System::Data;<br/>
using namespace System::Drawing;<br/>
using namespace System::Linq;<br/>
<br/>
using namespace System::Net;<br/>
using namespace System::Net::Sockets;<br/>
using namespace System::Threading;<br/>
using namespace System::Collections::Generic;<br/>
using namespace System::Text;<br/>
using namespace System::Reflection;<br/>
using namespace CServerApp;<br/>
<br/>
/// <summary><br/>
/// Summary for Form1<br/>
///<br/>
/// WARNING: If you change the name of this class, you will need to change the<br/>
/// Resource File Name property for the managed resource compiler tool<br/>
/// associated with all .resx files this class depends on. Otherwise,<br/>
/// the designers will not be able to interact properly with localized<br/>
/// resources associated with this form.<br/>
/// </summary><br/>
public ref class Form1 : public System::Windows::Forms::Form<br/>
{<br/>
<br/>
public:<br/>
<br/>
Form1(void)<br/>
{<br/>
//Client clientApp;<br/>
//BindingList<Client^>^ clientList = gcnew BindingList<Client^>();<br/>
//int m_clientCount = 0;<br/>
//int m_indexClientX = 0;<br/>
<br/>
clientList = gcnew BindingList<Client^>();<br/>
m_clientCount = 0;<br/>
m_indexClientX = 0;<br/>
InitializeComponent();<br/>
m_workerSocketList = ArrayList::Synchronized(gcnew ArrayList());<br/>
UpdateControls(false);<br/>
<br/>
//<br/>
//TODO: Add the constructor code here<br/>
//<br/>
}<br/>
<br/>
protected:<br/>
/// <summary><br/>
/// Clean up any resources being used.<br/>
/// </summary><br/>
~Form1()<br/>
{<br/>
if (components)<br/>
{<br/>
//MessageBox::Show("Hello");<br/>
delete components;<br/>
//delete clientList;<br/>
<br/>
}<br/>
//if (clientList)<br/>
//{<br/>
// delete clientList;<br/>
//}<br/>
}<br/>
private: System::Windows::Forms::Label^ labelIP;<br/>
private: System::Windows::Forms::Label^ labelPort;<br/>
private: System::Windows::Forms::Label^ labelConnectedClients;<br/>
protected:<br/>
<br/>
protected:<br/>
<br/>
<br/>
private: System::Windows::Forms::TextBox^ textBoxIP;<br/>
private: System::Windows::Forms::TextBox^ textBoxPort;<br/>
<br/>
<br/>
private: System::Windows::Forms::Button^ buttonStartMonitoring;<br/>
private: System::Windows::Forms::Button^ buttonStopMonitoring;<br/>
private: System::Windows::Forms::DataGridView^ dataGridViewConnectedClients;<br/>
<br/>
private: System::Windows::Forms::BindingSource^ clientBindingSource;<br/>
private: System::ComponentModel::IContainer^ components;<br/>
<br/>
<br/>
private:<br/>
/// <summary><br/>
String^ GetIP()<br/>
{<br/>
String^ strHostName = Dns::GetHostName();<br/>
<br/>
// Find host by name<br/>
//IPHostEntry^ iphostentry = Dns::GetHostEntry(strHostName);<br/>
<br/>
// // Grab the first IP addresses<br/>
// String^ IPStr = "";<br/>
//for ( int index = 0; index < iphostentry->AddressList->Length; index++ ){<br/>
// IPStr = iphostentry->AddressList[index]->ToString();<br/>
// return IPStr;<br/>
// }<br/>
// return IPStr;<br/>
return strHostName;<br/>
}<br/>
Client^ clientApp;<br/>
BindingList<Client^>^ clientList;<br/>
int m_clientCount;<br/>
int m_indexClientX;<br/>
Socket^ m_mainSocket;<br/>
ArrayList^ m_workerSocketList;<br/>
<br/>
<br/>
public:<br/>
delegate void UpdateRichEditCallback(String^ text);<br/>
delegate void UpdateClientListCallback();<br/>
delegate void UpdateClientMessageCallback(Client^ clientX, String^ message);<br/>
delegate void AddClientListCallback(BindingList<Client^>^ clientList, Client^ clientX);<br/>
//public delegate void RemoveClientListCallback(ref BindingList<Client> clientList, Client clientX);<br/>
delegate void RemoveClientListCallback(BindingList<Client^>^ clientList, int indexClientX);<br/>
delegate void UpdateClientAlertCallback(Client^ clientX, int alert);<br/>
//delegate void OnClientConnect(IAsyncResult^ asyn);<br/>
AsyncCallback^ pfnWorkerCallBack;<br/>
<br/>
<br/>
<br/>
/// </summary><br/>
<br/>
<br/>
#pragma region Windows Form Designer generated code<br/>
/// <summary><br/>
/// Required method for Designer support - do not modify<br/>
/// the contents of this method with the code editor.<br/>
/// </summary><br/>
void InitializeComponent(void)<br/>
{<br/>
this->components = (gcnew System::ComponentModel::Container());<br/>
this->labelIP = (gcnew System::Windows::Forms::Label());<br/>
this->labelPort = (gcnew System::Windows::Forms::Label());<br/>
this->labelConnectedClients = (gcnew System::Windows::Forms::Label());<br/>
this->textBoxIP = (gcnew System::Windows::Forms::TextBox());<br/>
this->textBoxPort = (gcnew System::Windows::Forms::TextBox());<br/>
this->buttonStartMonitoring = (gcnew System::Windows::Forms::Button());<br/>
this->buttonStopMonitoring = (gcnew System::Windows::Forms::Button());<br/>
this->dataGridViewConnectedClients = (gcnew System::Windows::Forms::DataGridView());<br/>
this->clientBindingSource = (gcnew System::Windows::Forms::BindingSource(this->components));<br/>
(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->dataGridViewConnectedClients))->BeginInit();<br/>
(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->clientBindingSource))->BeginInit();<br/>
this->SuspendLayout();<br/>
//<br/>
// labelIP<br/>
//<br/>
this->labelIP->AutoSize = true;<br/>
this->labelIP->Location = System::Drawing::Point(21, 19);<br/>
this->labelIP->Name = L"labelIP";<br/>
this->labelIP->Size = System::Drawing::Size(94, 13);<br/>
this->labelIP->TabIndex = 0;<br/>
this->labelIP->Text = L"Server Host Name";<br/>
//<br/>
// labelPort<br/>
//<br/>
this->labelPort->AutoSize = true;<br/>
this->labelPort->Location = System::Drawing::Point(21, 53);<br/>
this->labelPort->Name = L"labelPort";<br/>
this->labelPort->Size = System::Drawing::Size(60, 13);<br/>
this->labelPort->TabIndex = 1;<br/>
this->labelPort->Text = L"Server Port";<br/>
this->labelPort->TextAlign = System::Drawing::ContentAlignment::TopCenter;<br/>
//<br/>
// labelConnectedClients<br/>
//<br/>
this->labelConnectedClients->AutoSize = true;<br/>
this->labelConnectedClients->Location = System::Drawing::Point(21, 88);<br/>
this->labelConnectedClients->Name = L"labelConnectedClients";<br/>
this->labelConnectedClients->Size = System::Drawing::Size(93, 13);<br/>
this->labelConnectedClients->TabIndex = 2;<br/>
this->labelConnectedClients->Text = L"Connected Clients";<br/>
//<br/>
// textBoxIP<br/>
//<br/>
this->textBoxIP->Location = System::Drawing::Point(131, 19);<br/>
this->textBoxIP->Name = L"textBoxIP";<br/>
this->textBoxIP->ReadOnly = true;<br/>
this->textBoxIP->Size = System::Drawing::Size(128, 20);<br/>
this->textBoxIP->TabIndex = 3;<br/>
//<br/>
// textBoxPort<br/>
//<br/>
this->textBoxPort->Location = System::Drawing::Point(131, 53);<br/>
this->textBoxPort->Name = L"textBoxPort";<br/>
this->textBoxPort->Size = System::Drawing::Size(72, 20);<br/>
this->textBoxPort->TabIndex = 4;<br/>
this->textBoxPort->Text = L"8000";<br/>
//<br/>
// buttonStartMonitoring<br/>
//<br/>
this->buttonStartMonitoring->Enabled = false;<br/>
this->buttonStartMonitoring->Location = System::Drawing::Point(306, 19);<br/>
this->buttonStartMonitoring->Name = L"buttonStartMonitoring";<br/>
this->buttonStartMonitoring->Size = System::Drawing::Size(75, 54);<br/>
this->buttonStartMonitoring->TabIndex = 5;<br/>
this->buttonStartMonitoring->Text = L"Start Monitoring";<br/>
this->buttonStartMonitoring->UseVisualStyleBackColor = true;<br/>
this->buttonStartMonitoring->Click += gcnew System::EventHandler(this, &Form1::buttonStartMonitoring_Click);<br/>
//<br/>
// buttonStopMonitoring<br/>
//<br/>
this->buttonStopMonitoring->Location = System::Drawing::Point(397, 19);<br/>
this->buttonStopMonitoring->Name = L"buttonStopMonitoring";<br/>
this->buttonStopMonitoring->Size = System::Drawing::Size(75, 54);<br/>
this->buttonStopMonitoring->TabIndex = 6;<br/>
this->buttonStopMonitoring->Text = L"Stop Monitoring";<br/>
this->buttonStopMonitoring->UseVisualStyleBackColor = true;<br/>
//<br/>
// dataGridViewConnectedClients<br/>
//<br/>
this->dataGridViewConnectedClients->AllowUserToOrderColumns = true;<br/>
this->dataGridViewConnectedClients->AutoGenerateColumns = false;<br/>
this->dataGridViewConnectedClients->ColumnHeadersHeightSizeMode = System::Windows::Forms::DataGridViewColumnHeadersHeightSizeMode::AutoSize;<br/>
this->dataGridViewConnectedClients->DataSource = this->clientBindingSource;<br/>
this->dataGridViewConnectedClients->Location = System::Drawing::Point(24, 117);<br/>
this->dataGridViewConnectedClients->Name = L"dataGridViewConnectedClients";<br/>
this->dataGridViewConnectedClients->Size = System::Drawing::Size(448, 120);<br/>
this->dataGridViewConnectedClients->TabIndex = 7;<br/>
//<br/>
// clientBindingSource<br/>
//<br/>
this->clientBindingSource->DataSource = CServerApp::Client::typeid;<br/>
//<br/>
// Form1<br/>
//<br/>
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);<br/>
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;<br/>
this->ClientSize = System::Drawing::Size(492, 262);<br/>
this->Controls->Add(this->dataGridViewConnectedClients);<br/>
this->Controls->Add(this->buttonStopMonitoring);<br/>
this->Controls->Add(this->buttonStartMonitoring);<br/>
this->Controls->Add(this->textBoxPort);<br/>
this->Controls->Add(this->textBoxIP);<br/>
this->Controls->Add(this->labelConnectedClients);<br/>
this->Controls->Add(this->labelPort);<br/>
this->Controls->Add(this->labelIP);<br/>
this->Name = L"Form1";<br/>
this->Text = L"Centralized Monitoring Server";<br/>
(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->dataGridViewConnectedClients))->EndInit();<br/>
(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->clientBindingSource))->EndInit();<br/>
this->ResumeLayout(false);<br/>
this->PerformLayout();<br/>
<br/>
}<br/>
<br/>
<br/>
#pragma endregion<br/>
private: System::Void buttonStartMonitoring_Click(System::Object^ sender, System::EventArgs^ e) {<br/>
try<br/>
{<br/>
// Check the port value<br/>
if (textBoxPort->Text == "")<br/>
{<br/>
MessageBox::Show("Please enter a Port Number");<br/>
return;<br/>
}<br/>
String^ portStr = textBoxPort->Text;<br/>
int port = System::Convert::ToInt32(portStr);<br/>
// Create the listening socket...<br/>
m_mainSocket = gcnew Socket(AddressFamily::InterNetwork,<br/>
SocketType::Stream,<br/>
ProtocolType::Tcp);<br/>
IPEndPoint^ ipLocal = gcnew IPEndPoint(IPAddress::Any, port);<br/>
// Bind to local IP Address...<br/>
m_mainSocket->Bind(ipLocal);<br/>
// Start listening...<br/>
m_mainSocket->Listen(4);<br/>
// Create the call back for any client connections...<br/>
m_mainSocket->BeginAccept(gcnew AsyncCallback(this, &CServerApp::Form1::OnClientConnect), nullptr);<br/>
UpdateControls(true);<br/>
}<br/>
catch (SocketException^ se)<br/>
{<br/>
MessageBox::Show(se->Message);<br/>
}<br/>
}<br/>
<br/>
private: void UpdateControls(bool listening)<br/>
{<br/>
buttonStartMonitoring->Enabled = !listening;<br/>
buttonStopMonitoring->Enabled = listening;<br/>
}<br/>
<br/>
public: void OnClientConnect(IAsyncResult^ asyn)<br/>
{<br/>
try<br/>
{<br/>
// Here we complete/end the BeginAccept() asynchronous call<br/>
// by calling EndAccept() - which returns the reference to<br/>
// a new Socket object<br/>
Socket^ workerSocket = m_mainSocket->EndAccept(asyn);<br/>
<br/>
// Now increment the client count for this client<br/>
// in a thread safe manner<br/>
Interlocked::Increment(m_clientCount);<br/>
<br/>
// Add the workerSocket reference to our ArrayList<br/>
m_workerSocketList->Add(workerSocket);<br/>
<br/>
//TODO: Put here all the control messages communication<br/>
// Send a welcome message to client<br/>
String^ msg = "Welcome client " + m_clientCount + "n";<br/>
<br/>
<br/>
clientApp = gcnew Client(m_clientCount, workerSocket->RemoteEndPoint->ToString());<br/>
AddElementToClientListDataGrid(clientList, clientApp);<br/>
<br/>
SendMsgToClient(msg, m_clientCount);<br/>
<br/>
// Update the list box showing the list of clients (thread safe call)<br/>
UpdateClientListControl();<br/>
<br/>
// Let the worker Socket do the further processing for the<br/>
// just connected client<br/>
WaitForData(workerSocket, m_clientCount);<br/>
<br/>
// Since the main Socket is now free, it can go back and wait for<br/>
// other clients who are attempting to connect<br/>
<br/>
m_mainSocket->BeginAccept(gcnew AsyncCallback(this, &CServerApp::Form1::OnClientConnect), this);<br/>
// MessageBox::Show("Test");<br/>
<br/>
}<br/>
catch (ObjectDisposedException^)<br/>
{<br/>
System::Diagnostics::Debugger::Log(0, "1", "n OnClientConnection: Socket has been closedn");<br/>
}<br/>
catch (SocketException^ se)<br/>
{<br/>
MessageBox::Show(se->Message);<br/>
}<br/>
<br/>
}<br/>
<br/>
private: void AddElementToClientListDataGrid(BindingList<Client^>^ clientList, Client^ clientX)<br/>
{<br/>
if (InvokeRequired) // Is this called from a thread other than the one created<br/>
// the control<br/>
{<br/>
<br/>
// We cannot update the GUI on this thread.<br/>
// All GUI controls are to be updated by the main (GUI) thread.<br/>
// Hence we will use the invoke method on the control which will<br/>
// be called when the Main thread is free<br/>
// Do UI update on UI thread<br/>
<br/>
List<Object^>^ objectList = gcnew List<Object^>();<br/>
<br/>
objectList->Add(clientList);<br/>
objectList->Add(clientX);<br/>
<br/>
//Object objectList[2];<br/>
//objectList[0] = clientList;<br/>
//objectList[1] = clientX;<br/>
//dataGridViewConnectedClients->BeginInvoke(gcnew AddClientListCallback(AddElementToClientList), objectList);<br/>
dataGridViewConnectedClients->BeginInvoke(gcnew AddClientListCallback(this, &CServerApp::Form1::AddElementToClientList), objectList);<br/>
}<br/>
else<br/>
{<br/>
// This is the main thread which created this control, hence update it<br/>
// directly<br/>
AddElementToClientList(clientList, clientX);<br/>
}<br/>
}<br/>
<br/>
<br/>
private: void AddElementToClientList(BindingList<Client^>^ clientList, Client^ clientX)<br/>
{<br/>
clientList->Add(clientX);<br/>
}<br/>
<br/>
public: void WaitForData(Socket^ soc, int clientNumber)<br/>
{<br/>
try<br/>
{<br/>
if (pfnWorkerCallBack == nullptr)<br/>
{<br/>
// Specify the call back function which is to be<br/>
// invoked when there is any write activity by the<br/>
// connected client<br/>
pfnWorkerCallBack = gcnew AsyncCallback(this, &CServerApp::Form1::OnDataReceived);<br/>
}<br/>
SocketPacket^ theSocPkt = gcnew SocketPacket(soc, clientNumber);<br/>
<br/>
//soc.BeginReceive(theSocPkt.dataBuffer, 0,<br/>
// theSocPkt.dataBuffer.Length,<br/>
// SocketFlags.None,<br/>
// pfnWorkerCallBack,<br/>
// theSocPkt);<br/>
}<br/>
catch (SocketException^ se)<br/>
{<br/>
MessageBox::Show(se->Message);<br/>
}<br/>
}<br/>
<br/>
public: void OnDataReceived(IAsyncResult^ asyn)<br/>
{<br/>
SocketPacket^ socketData = (SocketPacket^) asyn->AsyncState;<br/>
//Data data = (Data) asyn.AsyncState;<br/>
<br/>
<br/>
<br/>
Encoding^ utf8 = Encoding::UTF8;<br/>
Encoding^ ascii = Encoding::ASCII;<br/>
// Complete the BeginReceive() asynchronous call by EndReceive() method<br/>
// which will return the number of characters written to the stream<br/>
// by the client<br/>
//String^ byteString = gcnew String(socketData->dataBuffer->ToString());<br/>
array<Byte>^ utf8Bytes = utf8->GetBytes(socketData->dataBuffer->ToString());<br/>
<br/>
int iRx = socketData->m_currentSocket->EndReceive(asyn);<br/>
<br/>
array<Byte>^ asciiBytes = Encoding::Convert( utf8, ascii, utf8Bytes );<br/>
<br/>
array<Char>^ asciiChars = gcnew array<Char>(iRx+1);<br/>
ascii->GetChars( asciiBytes, 0, asciiBytes->Length, asciiChars, 0 );<br/>
String^ asciiString = gcnew String( asciiChars );<br/>
<br/>
<br/>
<br/>
//String^ asciiString = gcnew String( utf8Bytes );<br/>
<br/>
<br/>
//Data message = ByteArrayToObject(socketData.dataBuffer) as Data;<br/>
//Data message = ByteArrayToObject(socketData.dataBuffer) as Data;<br/>
<br/>
//switch (message.header)<br/>
//{<br/>
// case 1:<br/>
// string msg = "" + socketData.m_clientNumber + ":";<br/>
// //clientApp = clientList.ElementAt(socketData.m_clientNumber);<br/>
// SetClientMessageDataGridView(ref clientApp, szData);<br/>
// //AppendToRichEditControl(msg + szData);<br/>
<br/>
// // Send back the reply to the client<br/>
// string replyMsg = "Server Reply:" + szData.ToUpper();<br/>
// // Convert the reply to byte array<br/>
// byte[] byData = System.Text.Encoding.ASCII.GetBytes(replyMsg);<br/>
<br/>
// Socket workerSocket = (Socket)socketData.m_currentSocket;<br/>
// workerSocket.Send(byData);<br/>
// break;<br/>
// case 2:<br/>
// //Console.WriteLine("Case 2");<br/>
// break;<br/>
// default:<br/>
// //Console.WriteLine("Default case");<br/>
// break;<br/>
//}<br/>
<br/>
}<br/>
<br/>
void SendMsgToClient(String^ msg, int clientNumber)<br/>
{<br/>
// Convert the reply to byte array<br/>
Encoding^ ascii = Encoding::ASCII;<br/>
array<Byte>^ byData = ascii->GetBytes(msg);<br/>
<br/>
Socket^ workerSocket = (Socket^) m_workerSocketList[clientNumber - 1];<br/>
workerSocket->Send(byData);<br/>
}<br/>
<br/>
private: void UpdateClientListControl()<br/>
{<br/>
if (InvokeRequired) // Is this called from a thread other than the one created<br/>
// the control<br/>
{<br/>
// We cannot update the GUI on this thread.<br/>
// All GUI controls are to be updated by the main (GUI) thread.<br/>
// Hence we will use the invoke method on the control which will<br/>
// be called when the Main thread is free<br/>
// Do UI update on UI thread<br/>
dataGridViewConnectedClients->BeginInvoke(gcnew UpdateClientListCallback(this, &CServerApp::Form1::UpdateClientList), nullptr);<br/>
}<br/>
else<br/>
{<br/>
// This is the main thread which created this control, hence update it<br/>
// directly<br/>
UpdateClientList();<br/>
}<br/>
}<br/>
<br/>
void UpdateClientList()<br/>
{<br/>
this->dataGridViewConnectedClients->EndEdit();<br/>
this->dataGridViewConnectedClients->Refresh();<br/>
this->Refresh();<br/>
}<br/>
};<br/>
}<br/>
<br/>
<br/>
<br/>

View the full article
 
Back
Top