2011-04-20 90 views
2

我正在同時共享多個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 { } 
} 
+0

你需要詳細說明你的問題好,代碼樣本也可能幫助 – radman 2011-04-20 05:01:45

回答

3

您所看到的錯誤也不例外。您看到的消息只是讓您知道,native框架位於stack的頂部,而不是managed框架的頂部。

您看到的錯誤可能與數組無關 - 但是如果沒有看到您的某些代碼很難說清楚。

多線程程序涉及兩個非常常見的問題。如果我不得不猜測,你會得到一個InvalidOperationException,因爲「對象當前正在使用」或因爲「跨線程操作無效」。

如果第一個是這樣的話,你需要使用類似:

lock (myObject) 
{ 
    // Alter myObject 
} 

看到Locks

而且,如果第二個的情況下,你需要使用類似:

Invoke(new MethodInvoker(delegate() 
    { 
    // Alter stuff in Forms/Controls 
    })); 

Invoke

如果你可以發佈你正在獲得的確切異常和產生它的代碼,這將非常有幫助。


編輯:您發佈了一段代碼來查看。這是非常無益的。 你說行導致它是

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); 
} 
+0

請參閱代碼和告訴我的解決方案,感謝重播 – 2011-04-20 05:42:35

+0

見我的編輯和發佈的內容是在MessageBox – Ozzah 2011-04-20 06:04:22

+0

我會請修改有問題的代碼,請參閱我的編輯&我把這個聲明,但沒有異常捕獲,但線程停止在此聲明excution沒有進一步處理此消息將顯示在_opcserver變量的本地值 – 2011-04-20 07:16:44