Multi-Threading GUI control..problem.

G

GoodMorningSky

My app creates muti-thread and the status of each thread are shown on a
datagrid.
I got following error message. from Application.Run(new frmMDIMain());
The strange thing is no exception occurs for the first try. But the
exception occurs from 2nd try.
I closed the form and did 2nd try it still throws the exception.
What's wrong?


Unhandled Exception: System.NullReferenceException: Object reference not set
to an instance of an object.
at System.Windows.Forms.UnsafeNativeMethods.PeekMessage(MSG& msg,
HandleRef hwnd, Int32 msgMin, Int32 msgMax, Int32 remove)
at
System.Windows.Forms.ComponentManager.System.Windows.Forms.UnsafeNativeMetho
ds+IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason,
Int32 pvLoopData)
at System.Windows.Forms.ThreadContext.RunMessageLoopInner(Int32 reason,
ApplicationContext context)
at System.Windows.Forms.ThreadContext.RunMessageLoop(Int32 reason,
ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at TimeClockAdmin.frmMDIMain.Main() in c:\projects\new time clock
release\new time clock hq\timeclockadmin\frmmdimain.cs:line 496The program
'[2952] TimeClockAdmin.exe' has exited with code 0 (0x0).



The following is code part of the code.

private void Transfer()
{
try
{
Thread th =Thread.CurrentThread;
//Debug.WriteLine(th.Name);
int idx = Convert.ToInt32(th.Name);
string ip = deptList.Rows[idx]["IP"].ToString();
string comp = deptList.Rows[idx]["Comp"].ToString();
string dept = deptList.Rows[idx]["Dept"].ToString();
Debug.WriteLine(idx + ", " + deptList.Rows[idx]["IP"]);

DateTime from;
DateTime to;

if(this.chkFromLast.Checked)
{
from =(DateTime)( new DBHandler().ExecuteScalarOnHQ("SELECT
LastTransferedTime FROM tblDepartment WHERE CompanyCode='" + comp + "' AND
DepartmentCode='" + dept + "'"));
to = DateTime.Now;
}
else
{
from = dtpFrom.Value;
to = dtpTo.Value;
}

DoPeriodicalTransfer(idx,from, to, comp, dept, ip);
}
catch(Exception ex)
{
Debug.WriteLine(ex.Message);
}


}


/// <summary>
/// Transfer data for the period passed.
/// Data is the tables rows that are needed for operation.
/// If transfer fails check network connection by Pinging.
/// </summary>
/// <param name="idx"></param>
/// <param name="fd"></param>
/// <param name="td"></param>
/// <param name="ip"></param>
private void DoPeriodicalTransfer(int idx, DateTime fd, DateTime td,
string compCode, string deptCode, string ip)
{
MethodInvoker delIncTotal = new MethodInvoker(this.IncTotal);
MethodInvoker delIncSuc = new MethodInvoker(this.IncSuc);
MethodInvoker delIncFail = new MethodInvoker(this.IncFail);

try
{
string cnnStr;
DateTime tranTime;

try
{
DBHandler dbh=new DBHandler();
tranTime = DateTime.Now;

string strSqlLocal, strSqlHQ;
DataTable tbl;
//ComponentInterfaces.IRemotingDBHandler remoteObj;

//deptList.Rows[idx]["Message"] = "Transferring....";
this.MsgEach(idx, "Message","Transferring....");
cnnStr = DBHandler.GetDBDeptConnectionString(compCode, deptCode);

// tblPunchData
strSqlLocal = "spPunchData; 43 '', '" + fd + "', '" + td + "'";
this.MsgEach(idx, "Message", "Selecting Punch data");
tbl = this.GetRemoteObj().ExecuteDataSet(strSqlLocal,
cnnStr).Tables[0];
for(int i=0; i < tbl.Rows.Count; i++)
{
DataRow row = tbl.Rows;
strSqlHQ = "spPunchData; 42 '" + row["userID"] + "', '" +
row["punchtime"] + "', '" + row["punchType"] + "', " + row["EditType"] + ",
'" +
row["companyCode"] + "', '" + row["DepartmentCode"] + "', '" +
row["UpdateTime"] + "', " +
((bool)row["WeekClosed"]? 1: 0) + ", " + ((bool)row["PayrollClosed"]?
1: 0) + ", '" +
row["AdditionalDate"] + "', " + ((bool)row["AdditionalDateMinus"]? 1:
0) + ", " +
row["PunchPayType"] + ", " + (row["uniqueID"]==DBNull.Value ? "NULL":
row["uniqueID"]);
dbh.ExecuteNonQueryOnHQ(strSqlHQ);
this.MsgEach(idx, "Message", "PunchData: " + (i + 1) + "/" +
tbl.Rows.Count );
}

// tblPunchData for Remote User
strSqlLocal = "spPunchData; 44 ";
this.MsgEach(idx, "Message", "Selecting Punch data for remoting..");
tbl = this.GetRemoteObj().ExecuteDataSet(strSqlLocal,
cnnStr).Tables[0];
string delWhere, orOp;
delWhere = " WHERE ";
orOp = " OR ";
for(int i=0; i < tbl.Rows.Count; i++)
{
DataRow row = tbl.Rows;
strSqlHQ = "spPunchData_Posting; 4 '" + row["userID"] + "', '" +
row["punchtime"] + "', '" +
row["punchType"] + "', " + row["EditType"] + ", " +
row["PunchPayType"] + " , '" + row["companyCode"] + "', '" +
row["DepartmentCode"] + "', '" + row["UpdateTime"] + "', NULL, 0";
//-- no uniqueID transfered since it will be generated on Home dept db when
inserted
dbh.ExecuteNonQueryOnHQ(strSqlHQ);
delWhere += "( UserID = '" + row["userID"] + "' AND UniqueID = " +
row["uniqueID"] + " ) " + orOp;

this.MsgEach(idx, "Message", "PunchData_Remote: " + (i + 1) + "/" +
tbl.Rows.Count );
}

if (!delWhere.Equals(" WHERE "))
{
strSqlLocal = "DELETE tblPunchData " + delWhere.Substring(0,
delWhere.Length - orOp.Length);
this.GetRemoteObj().ExecuteNonQuery(strSqlLocal, cnnStr, true);
}

// tblUser
strSqlLocal = "spUser; 19 '" + fd + "', '" + td + "'";
this.MsgEach(idx, "Message", "Selecting User data...");
tbl = this.GetRemoteObj().ExecuteDataSet(strSqlLocal,
cnnStr).Tables[0];
for(int i=0; i < tbl.Rows.Count; i++)
{
DataRow row = tbl.Rows;
strSqlHQ = "spUser; 18 '" + row["userID"] + "', " +
DBHandler.EncodeSql(row["FirstName"], true) + ", " +
DBHandler.EncodeSql(row["LastName"], true) + ", '" +
row["EmployeeLevel"] + "', '" + row["startdate"] + "', '" +
row["TerminateDate"] + "', " +
((bool)row["ExceptDailyOvertime"]? 1: 0) + ", '" + row["companyCode"]
+ "', '" + row["DepartmentCode"] + "', " +
((bool)row["Deleted"]? 1: 0) + ", '" + row["Fingerprint"] + "', '" +
row["UpdateTime"] + "'";
dbh.ExecuteNonQueryOnHQ(strSqlHQ);
this.MsgEach(idx, "Message","User: " + (i + 1) + "/" +
tbl.Rows.Count );
}

//-- clean up remote users who don't have any punch data
strSqlLocal = "spUserRemote; 4 ";
this.GetRemoteObj().ExecuteNonQuery(strSqlLocal, cnnStr, true);

// tblPayrollReport
string str = "", strOr = " OR ";
strSqlLocal = "spPayrollReport; 8 '', '" + fd + "', '" + td + "'";
this.MsgEach(idx, "Message", "Selecting PayrollReport data...");
tbl = this.GetRemoteObj().ExecuteDataSet(strSqlLocal,
cnnStr).Tables[0];
for(int i=0; i < tbl.Rows.Count; i++)
{
DataRow row = tbl.Rows;
str = str + " ( UserID = '" + row["userID"] + "' AND PayrollPeriodID =
'" + row["PayrollPeriodID"] + "' )" + strOr;
}
if(str != "")
{
str = "DELETE tblPayrollReport WHERE " + str.Substring(0, str.Length -
strOr.Length);
}

strSqlLocal = "spPayrollReport; 9 '', '" + fd + "', '" + td + "'";
tbl = this.GetRemoteObj().ExecuteDataSet(strSqlLocal,
cnnStr).Tables[0];

strSqlHQ = str;
if(strSqlHQ != "") //deleting data first before inserting
{
dbh.ExecuteNonQueryOnHQ(strSqlHQ);
}

for(int i=0; i < tbl.Rows.Count; i++)
{
DataRow row = tbl.Rows;
strSqlHQ = "spPayrollReport; 7 " + row["tblID"] + ", '" +
row["userID"] + "', " + row["Weeks"] + ", '" +
row["TimeIn"] + "', '" + row["TimeOut"] + "', '" + row["JobCode"] +
"', '" + row["Break"] + "', " +
row["Hours"] + ", " + row["reg"] + ", " + row["Ovt1"] + ", " +
row["Ovt2"] + ", " + row["DayTotal"] + ", " +
(row["AdditionalDate"]==DBNull.Value ? "NULL" :
row["AdditionalDate"]) + ", " + (row["AdditionalDateMinus"]==DBNull.Value ?
"NULL" : row["AdditionalDateMinus"] ) + ", '" +
row["companyCode"] + "', '" + row["DepartmentCode"] + "', '" +
row["UpdateTime"] + "', '" +
row["PayrollPeriodID"] + "', " + row["PunchPayType"] + ", '" +
row["PunchPayTypeName"] + "', '" +
row["TypeOfDay"] + "', " + row["EditType"];
dbh.ExecuteNonQueryOnHQ(strSqlHQ);
this.MsgEach(idx, "Message", "PayrollReport: " + (i + 1) + "/" +
tbl.Rows.Count );
}

// tblLogPunchData
strSqlLocal = "spLogPunchData2; 6 '" + fd + "', '" + td + "'";
tbl = this.GetRemoteObj().ExecuteDataSet(strSqlLocal,
cnnStr).Tables[0];
for(int i=0; i < tbl.Rows.Count; i++)
{
DataRow row = tbl.Rows;
strSqlHQ = "spLogPunchData2; 5 " + row["id"] + ", " +
DBHandler.EncodeSql(row["EmpName"],true) + ", '" +
row["EmpLevelName"] + "', '" + row["EmpID"] + "', '" +
row["EmpJobCode"] + "', " +
DBHandler.EncodeSql(row["ModName"], true) + ", '" +
row["ModLevelName"] + "', '" + row["ModID"] + "', '" +
row["ModJobCode"] + "', '" + row["Type"] + "', '" + row["Old_TimeIn"]
+ "', '" +
row["Old_TimeOut"] + "', '" + row["Old_PunchType"] + "', '" +
row["Old_PunchPayType"] + "', '" +
row["New_TimeIn"] + "', '" + row["New_TimeOut"] + "', '" +
row["New_PunchType"] + "', '" +
row["New_PunchPayType"] + "', '" + row["UpdateTime"] + "', '" +
row["CompanyCode"] + "', '" + row["DepartmentCode"] + "'";
dbh.ExecuteNonQueryOnHQ(strSqlHQ);
this.MsgEach(idx, "Message", "Log_Punch: " + (i + 1) + "/" +
tbl.Rows.Count );
}

// tblLogManager
strSqlLocal = "spLogManager; 6 '" + fd + "', '" + td + "'";
tbl = this.GetRemoteObj().ExecuteDataSet(strSqlLocal,
cnnStr).Tables[0];
for(int i=0; i < tbl.Rows.Count; i++)
{
DataRow row = tbl.Rows;
strSqlHQ = "spLogManager; 5 " + row["id"] + ", " + row["Modifier"] +
", '" + row["LoginTime"] + "', '" +
row["LogOutTime"] + "', '" + row["CompanyCode"] + "', '" +
row["DepartmentCode"] + "'";
dbh.ExecuteNonQueryOnHQ(strSqlHQ);
this.MsgEach(idx, "Message", "Log_Manager: " + (i + 1) + "/" +
tbl.Rows.Count );
}

// tblLogUser
strSqlLocal = "spLogUser2; 5 '" + fd + "', '" + td + "'";
tbl = this.GetRemoteObj().ExecuteDataSet(strSqlLocal,
cnnStr).Tables[0];
for(int i=0; i < tbl.Rows.Count; i++)
{
DataRow row = tbl.Rows;
strSqlHQ ="spLogUser2; 4 " + row["id"] + ", '" + row["TargetUser"] +
"', " +
DBHandler.EncodeSql(row["ModName"], true) + ", '" +
row["ModLevelName"] + "', '" + row["ModID"] + "', '" + row["ModJobCode"] +
"', '" +
row["Type"] + "', " + DBHandler.EncodeSql(row["Old_Name"],true) + ",
'" + row["Old_EmpLevelName"] + "', '" +
row["Old_StartDate"] + "', '" + row["Old_TerminateDate"] + "', '" +
row["Old_CompCode"] + "', '" +
row["Old_DeptCode"] + "', '" + row["Old_Deleted"] + "', '" +
row["Old_FingerPrint"] + "', '" +
row["Old_UpdateTime"] + "', " +
DBHandler.EncodeSql(row["New_Name"], true) + ", '" +
row["New_EmpLevelName"] + "', '" + row["New_StartDate"] + "', '" +
row["New_TerminateDate"] + "', '" + row["New_CompCode"] + "', '" +
row["New_DeptCode"] + "', '" +
row["New_Deleted"] + "', '" + row["New_FingerPrint"] + "', '" +
row["UpdateTime"] + "', '" +
row["CompanyCode"] + "', '" + row["DepartmentCode"] + "'";
dbh.ExecuteNonQueryOnHQ(strSqlHQ);
this.MsgEach(idx, "Message", "Log_User: " + (i + 1) + "/" +
tbl.Rows.Count );
}

// tblLogTimeChange
strSqlLocal = "spLogTimeChange; 4 '" + fd + "', '" + td + "'";
tbl = this.GetRemoteObj().ExecuteDataSet(strSqlLocal,
cnnStr).Tables[0];
for(int i=0; i < tbl.Rows.Count; i++)
{
DataRow row = tbl.Rows;
strSqlHQ ="spLogTimeChange; 5 " + row["id"] + ", '" + row["Modifier"]
+ "', '" +
row["OldTime"] + "', '" + row["NewTime"] + "', " +
DBHandler.EncodeSql(row["Description"],true) + ", '" +
row["companyCode"] + "', '" + row["DepartmentCode"] + "'";
dbh.ExecuteNonQueryOnHQ(strSqlHQ);
this.MsgEach(idx, "Message", "Log_TimeChange: " + (i + 1) + "/" +
tbl.Rows.Count );
}

// Update LastTransferedTime on Local and HQ
strSqlLocal = "spSystemSetting; 6 '" + tranTime + "'";
this.GetRemoteObj().ExecuteNonQuery(strSqlLocal, cnnStr, true);
strSqlHQ = "spDepartment; 19 '" + compCode + "', '" + deptCode + "', '"
+ tranTime + "'";
dbh.ExecuteNonQueryOnHQ(strSqlHQ);

this.MsgEach(idx,"Message", "DONE");
this.MsgEach(idx, "Check", false);
lock(this.stateLock)
{
this.t_Suc++;
}
//this.Invoke(delIncSuc);

}
catch(Exception ex)
{
try
{
this.MsgEach(idx, "Message", "FAIL: " + ex.Message);
this.MsgEach(idx, "Check", true);
lock(this.stateLock)
{
this.t_Fail++;
}
//this.Invoke(delIncFail);

if(this.chkNetwork.Checked)
{
//Check network connection
this.MsgEach(idx, "Ping", "Start to ping..");
this.MsgEach(idx, "Ping", ((bool)objPing.PingRemote(ip)? "O": "X" ));
}
}
catch
{
Debug.WriteLine("Stop");
}
}
}

catch(Exception exx)
{
Debug.WriteLine("Bug: " + idx + ", " + exx.Message);
}

if(this.t_count <= 1)
{

this.ChangeMode(false);
}
lock(this.stateLock)
{
t_count--;
}
Invoke(delIncSuc);
Invoke(delIncFail);
Invoke(delIncTotal);
}
delegate void DataGridMsgDelegate(int idx, string colName, object msg);
private void MsgEach(int idx, string colName, object msg)
{
if(InvokeRequired) //if method is called by non-GUI thread.
{
//Tell GUI thread to call this method.
BeginInvoke(new DataGridMsgDelegate(MsgEach), new object[]{idx, colName,
msg});
return;
}
deptList.Rows[idx][colName] = msg;
}

private ComponentInterfaces.IRemotingDBHandler GetRemoteObj()
{
return
(ComponentInterfaces.IRemotingDBHandler)Activator.GetObject(typeof(Component
Interfaces.IRemotingDBHandler),
ConfigurationSettings.AppSettings["RemotingDBHandler"]);
}

readonly object stateLock = new object();//dgList

private int t_Suc = 0; //counting successful thread job
private int t_Fail = 0; //counting failed thread job
private int t_count=0; //counting total thread job.

private void IncTotal()
{
int tmpCnt;
lock(stateLock)
{
tmpCnt = t_count;
}
this.lbThread.Text = "Thread: " + tmpCnt.ToString();
}

private void DecTotal()
{
int tmpCnt;
lock(stateLock)
{
tmpCnt = t_count;
}
if(tmpCnt > 0)
{
lbThread.Text = "Thread: " + tmpCnt.ToString();
prBar.Value = prBar.Maximum - tmpCnt;
}
}

private void IncFail()
{
int tmpCnt;
lock(stateLock)
{
tmpCnt = t_Fail;
}
lbFail.Text = "Fail: " + tmpCnt.ToString();
}

private void IncSuc()
{
int tmpCnt;
lock(stateLock)
{
tmpCnt = t_Suc;
}
lbSuc.Text = "Suc: " + tmpCnt.ToString();
}

private void ResetCounters()
{
t_count = 0;
t_Suc = 0;
t_Fail = 0;
this.lbThread.Text = "Thread: " + t_count.ToString();
this.lbSuc.Text = "suc: " + t_Suc.ToString();
this.lbFail.Text = "fail: " + t_Fail.ToString();
Debug.WriteLine("count: " + t_count + ", suc: " + t_Suc + ", fail: " +
t_Fail);
}

private void ChangeMode(bool isRun)
{
this.btTransfer.Enabled = !isRun;
this.btTarget.Enabled = !isRun;
this.dgList.ReadOnly = isRun;
this.btCheckAll.Enabled = !isRun;
this.btUncheckAll.Enabled = !isRun;
this.dtpFrom.Enabled = !(isRun || this.chkFromLast.Checked);
this.dtpTo.Enabled = !(isRun || this.chkFromLast.Checked);
if(!isRun)
{
this.lbThread.Text = "DONE";
this.lbThread.ForeColor = Color.Red;
Cursor.Current = Cursors.Default;
MessageBox.Show(this, "Completed!", "Infromation");
}
else
{
Cursor.Current = Cursors.WaitCursor;
this.lbThread.ForeColor = Color.Black;
}
}
 
J

Jon Skeet [C# MVP]

GoodMorningSky said:
My app creates muti-thread and the status of each thread are shown on a
datagrid.
I got following error message. from Application.Run(new frmMDIMain());
The strange thing is no exception occurs for the first try. But the
exception occurs from 2nd try.
I closed the form and did 2nd try it still throws the exception.
What's wrong?

The following is code part of the code.

Instead of posting part of the code, including lots of stuff which is
basically irrelevant, please post *complete* code which only contains
enough to demonstrate the problem. None of your "business logic" is
likely to be necessary - only the way in which you create the form, run
things in threads and update the form.

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that.
 
Top