多线程编程

本文关键字:编程 多线程 | 更新日期: 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);
}