多线程编程
本文关键字:编程 多线程 | 更新日期: 2023-09-27 17:50:32
我同时在多个System.Threading.Timer
之间共享一个静态数组。这个数组只能被第一个计时器线程访问&第二个计时器将不会访问这个数组。显示一个异常:"错误不能计算表达式,本机帧在c#调用堆栈的顶部"请回复
public partial class OPC_server : DevExpress.XtraEditors.XtraForm
{
private System.Threading.Timer timer1;
private System.Threading.Timer timer2;
parameter param = new parameter();//another class
private static readonly object myLockHolder = new object();
private static readonly object myLockHolder1 = new object();
public static OpcServer[] _opcServer;
private void OPC_server_Load(object sender, EventArgs e)
{
getconnectedOPC();
}
public void getconnectedOPC()
{
ds = opcconn.GetOPCServerInfo();
int i=0;
DataTable dtOPC=new DataTable();
if (ds.Tables[0].Rows.Count != 0 || ds.Tables[0] != null)
{
dtOPC = ds.Tables[0].Copy();
_opcServer = new OpcServer[dtOPC.Rows.Count];
TimeSpan delayTime = new TimeSpan(0, 0, 1);
TimeSpan intervalTime = new TimeSpan(0, 0, 0, 0, 450);
foreach (DataRow row in dtOPC.Rows)
{
if (i <= dtOPC.Rows.Count)
{
//connetion(row);
getconnect(i, row, dtOPC.Rows.Count);
i++;
}
}
connetion(dtOPC.Rows.Count);
}
}
//connecting the server
public void getconnect(int conn, DataRow r,int rows)
{
DataSet ds2=new DataSet();
DataTable dt2 = new DataTable();
try
{
string machinename = Convert.ToString(r["OPCIPAddress"]);
string servername = Convert.ToString(r["OPCName"]);
_opcServer[conn] = new OpcServer();
int i = _opcServer[conn].Connect(machinename, servername);
if (i == 0)
{
opcconn.update("true", servername);
writelog(servername, "connected");
}
else
{
opcconn.update("false", servername);
writelog(servername, "disconnected");
}
}
catch (OPCException e)
{
servername = Convert.ToString(r["OPCName"]);
opcconn.update("false", servername);
writelog(servername, e.Message.ToString());
}
catch (ApplicationException e)
{
servername = Convert.ToString(r["OPCName"]);
opcconn.update("false", servername);
writelog(servername, "No instance server");
}
}
public void connetion(object state)
{
int k ,i,q=0;
k = (System.Int32)state;
DataSet dsgroup=new DataSet();
while(j < k)
{
try
{
bool val;
HRESULTS re;
SrvStatus status;
DateTime dt;
i = _opcServer[j].GetStatus(out status);
if (HRESULTS.Failed(i))
{
try
{
opcconn.update("false", _opcServer[j].ServerName.ToString());
string IP = opcconn.search(_opcServer[j].ServerName.ToString());
_opcServer[j].Connect(IP, _opcServer[j].ServerName.ToString());
opcconn.update("true", _opcServer[j].ServerName.ToString());
j++;
}
catch
{
opcconn.update("false", _opcServer[j].ServerName.ToString());
j++;
}
}
else
{
val = HRESULTS.Succeeded(i);
dsgroup = grpclass.getgroupinfo(j + 1);
if (dsgroup.Tables[0].Rows.Count != 0)
{
grpdt = new DataTable();
grpdt = dsgroup.Tables[0].Copy();
foreach (DataRow Row in grpdt.Rows)
{
if (groupcnt <= 128)
{
if (cntgroup < grpdt.Rows.Count)
{
grp = _opcServer[j].AddGroup((Convert.ToString(Row["GroupName"])), (Convert.ToBoolean(Row["setactive"])), (Convert.ToInt32(Row["refreshRate"])), 1);
ds1 = param.getparameter1(Convert.ToInt32(Row["groupID"]));
if (ds1.Tables[0].Rows.Count != 0)
{
dt1 = ds1.Tables[0].Copy();
int tq = 0;
item1 = new OPCItemDef[dt1.Rows.Count];
int clienthandle = 1;
foreach (DataRow r in dt1.Rows)
{
if (tq < item1.Length)
{
item1[tq] = new OPCItemDef(Convert.ToString(r["param_ID"]), Convert.ToBoolean(r["active"]), clienthandle, VarEnum.VT_EMPTY);
++clienthandle;
tq++;
}
}
int y = grp.AddItems(item1, out addRslt);
// thread started like each group assign one thread
OPCthread(Row, groupcnt);
groupcnt++;
cntgroup++;
}
}
}
}
}
cntgroup = 0;
j++;
}
}
catch (OPCException)
{
string servername = opcconn.getserver(j + 1);
string IPadd = opcconn.search(servername);
_opcServer[j].Connect(IPadd, servername);
}
catch (IndexOutOfRangeException)
{
j = 0;
}
catch (InvalidCastException e)
{
try
{
// writelog1(_opcServer[j].ServerName.ToString(), "disconnected");
opcconn.update("false", _opcServer[j].ServerName.ToString());
string IP = opcconn.search(_opcServer[j].ServerName.ToString());
_opcServer[j].Connect(IP, _opcServer[j].ServerName.ToString());
opcconn.update("true", _opcServer[j].ServerName.ToString());
j++;
}
catch
{
// writelog1(_opcServer[j].ServerName.ToString(), "connection failed");
opcconn.update("true", _opcServer[j].ServerName.ToString());
j++;
}
}
catch (ArgumentOutOfRangeException)
{
j = 0;
}
catch (NullReferenceException)
{
try
{
// writelog1("server'" + j + "' ", "no server instance");
OPC1 = opcconn.getserver(j + 1);
string IPA = opcconn.search(OPC1);
_opcServer[j].Connect(IPA, OPC1);
opcconn.update("true", OPC1);
writelog(OPC1, "connected");
j++;
}
catch (OPCException e)
{
opcconn.update("false", OPC1);
writelog(OPC1, e.Message.ToString());
j++;
}
catch (ApplicationException e)
{
opcconn.update("false", OPC1);
writelog(OPC1, "No instance server");
j++;
}
}
}
}
public void OPCthread(DataRow r2,int timerinfo)
{
if (timerinfo == 0)
{
int rer = Convert.ToInt32(r2["refreshRate"]);//at least 1 second
TimeSpan dueTime = new TimeSpan(0, 0,0,0,rer);
TimeSpan interval = new TimeSpan(0, 0, 0 ,0 ,rer);
timer1 = new System.Threading.Timer(register, r2, dueTime,interval);
}
else if (timerinfo == 1)
{
TimeSpan dueTime;
TimeSpan interval;
int rer1 = Convert.ToInt32(r2["refreshRate"]);
dueTime = new TimeSpan(0, 0, 0, 0, rer1);
interval = new TimeSpan(0, 0, 0, 0, rer1);
timer2 = new System.Threading.Timer(register1, r2, dueTime, interval);
}
}
public void register(object row1)
{
try
{
lock (myLockHolder)
{
int cnt = 0, cnt1 = 0;
ItemValue[] rVals;
OPCItemDef[] item;
OpcServer srv = new OpcServer();
string[] array;
//SrvStatus status1;
DataSet paramds = new DataSet();
DataTable paramdt = new DataTable();
DataRow dt = (System.Data.DataRow)row1;
int serverID = Convert.ToInt32(dt["OPCServerID"]);
paramds = param.getparameter(Convert.ToInt32(dt["groupID"]));
if (Convert.ToBoolean(dt["setactive"]) == true)
{
if (paramds != null && paramds.Tables[0].Rows.Count != 0)
{
paramdt = paramds.Tables[0].Copy();
int tq = 0;
item = new OPCItemDef[paramdt.Rows.Count];
int clienthandle = 1;
foreach (DataRow r in paramdt.Rows)
{
if (tq < item.Length)
{
item[tq] = new OPCItemDef(Convert.ToString(r["param_ID"]), Convert.ToBoolean(r["active"]), clienthandle, VarEnum.VT_EMPTY);
++clienthandle;
tq++;
}
}
array = new string[item.Length];
cnt1 = 0;
while (cnt1 < array.Length)
{
array[cnt1] = item[cnt1].ItemID;
cnt1++;
}
rVals = _opcServer[serverID - 1].Read(array, Convert.ToInt32(dt["refreshRate"]));
//this line i got the exception when i checking the value of the _opcserver varible in locals the it will be display as "error can not evaluate expression a native frame is on top of the call stack in c#" & thread will stop the execution.
param.update(rVals, Convert.ToInt32(dt["groupID"]));
}
}
}
}
catch (ThreadAbortException) { }
finally { }
}
public void register1(object row2)
{
try
{
lock (myLockHolder1)
{
int cnt = 0, cnt11 = 0;
ItemValue[] rVals1;
OPCItemDef[] item1;
OpcServer srv1 = new OpcServer();
string[] array1;
DataSet paramds1 = new DataSet();
DataTable paramdt1 = new DataTable();
DataRow dt1 = (System.Data.DataRow)row2;
int serverID1 = Convert.ToInt32(dt1["OPCServerID"]);
// Boolean gstatus = grpclass.getstatus(Convert.ToInt32(dt["groupID"]));
paramds1 = param.getparameter2(Convert.ToInt32(dt1["groupID"]));
if (Convert.ToBoolean(dt1["setactive"]) == true)
{
if (paramds1 != null)
{
paramdt1 = paramds1.Tables[0].Copy();
int tq1 = 0;
item1 = new OPCItemDef[paramdt1.Rows.Count];
int clienthandle1 = 1;
foreach (DataRow r in paramdt1.Rows)
{
if (tq1 < item1.Length)
{
item1[tq1] = new OPCItemDef(Convert.ToString(r["param_ID"]), Convert.ToBoolean(r["active"]), clienthandle1, VarEnum.VT_EMPTY);
clienthandle1++;
tq1++;
}
}
array1 = new string[item1.Length];
cnt11 = 0;
while (cnt11 < array1.Length)
{
array1[cnt11] = item1[cnt11].ItemID;
cnt11++;
}
rvals = _opcServer[serverID1 - 1].Read(array1, Convert.ToInt32(dt1["refreshRate"]));//this line i got the exception when i checking the value of the _opcserver varible in locals the it will be display as "error can not evaluate expression a native frame is on top of the call stack in c#" & thread will stop the execution.
param.update1(rVals1, Convert.ToInt32(dt1["groupID"]));
}
}
}
}
catch { }
finally { }
}
您看到的错误不是异常。你看到的消息只是让你知道一个本地帧在堆栈的顶部,而不是一个托管帧。
您看到的错误可能与数组无关,但是如果不查看一些代码,则很难判断。
在多线程程序中有两个非常常见的问题。如果我不得不猜测,你会得到一个InvalidOperationException
,因为"对象当前正在使用"或因为"跨线程操作无效"。
如果是第一种情况,您需要使用如下内容:
lock (myObject)
{
// Alter myObject
}
看到锁。
如果是第二种情况,你需要使用这样的语句:
Invoke(new MethodInvoker(delegate()
{
// Alter stuff in Forms/Controls
}));
看到调用。
如果你能发布你得到的异常和产生它的代码,那将会很有帮助。
编辑:你贴了一堆代码要看。这是非常无益的。你说导致它的行是
rvals = _opcServer[serverID1 - 1].Read(array1, Convert.ToInt32(dt1["refreshRate"]));
但是在你的代码中我看不到你已经声明了变量_opcServer。
正如我已经告诉过你的,本机框架消息不是一个异常,并不意味着你的程序有任何问题!-这只是调试器告诉你它不能给你托管变量的值。
请把这段代码放在行周围,以确定您得到的异常类型,并告诉我异常是什么。
try
{
rvals = _opcServer[serverID1 - 1].Read(array1, Convert.ToInt32(dt1["refreshRate"]));
}
catch (System.Exception ex)
{
System.Windows.Forms.MessageBox.Show("Exception: " + ex.GetType().ToString() +
"'r'nMessage: " + ex.Message);
}