2011-04-20 3 views
2

Je partage un tableau statique entre un nombre de System.Threading.Timer simultanément. Ce tableau n'est accessible que par le premier thread de temporisation & le second temporisateur n'accèdera pas à ce tableau. Une exception est affiché: « erreur ne peut pas évaluer l'expression d'un cadre natif est sur le dessus de la pile des appels en C# » s'il vous plaît répondreprogrammation multithread

code du projet:

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

vous devez préciser votre question mieux, un exemple de code est également susceptible d'aider – radman

Répondre

3

L'erreur que vous voyez est pas une exception . Le message que vous voyez est juste pour vous faire savoir qu'un cadre native est sur le dessus du stack au lieu d'un cadre managed.

Il est possible que l'erreur que vous voyez n'a rien à voir avec le tableau - mais il est difficile de le savoir sans voir une partie de votre code.

Il existe deux problèmes très courants liés aux programmes multithreads. Si je devais deviner, vous obtiendrez un InvalidOperationException soit parce que "l'objet est actuellement utilisé" ou parce que "l'opération d'inter-thread n'est pas valide".

Si le premier est le cas, vous devez utiliser quelque chose comme:

lock (myObject) 
{ 
    // Alter myObject 
} 

voir Locks.

Et si le second est le cas, vous devez utiliser quelque chose comme:

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

voir Invoke.

Il serait vraiment utile si vous pouviez publier l'Exception exacte que vous obtenez et le code qui le produit.


Modifier: Vous avez posté une montagne de code à parcourir. C'est très inutile. Vous dites que la ligne est à l'origine il

rvals = _opcServer[serverID1 - 1].Read(array1, Convert.ToInt32(dt1["refreshRate"])); 

mais nulle part dans votre code puis je vois que vous avez déclaré la _opcServer variable.

Comme je vous l'ai déjà dit, le message de trame natif n'est pas une exception et ne signifie pas qu'il y a quelque chose qui ne va pas dans votre programme! - c'est simplement le débogueur qui vous dit qu'il ne peut pas vous donner les valeurs des variables gérées.

Veuillez placer ce code autour de la ligne pour identifier le type d'exception que vous obtenez, et dites-moi ce qu'est l'exception.

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

s'il vous plaît voir le code et me dire la solution, merci pour la relecture –

+0

Voir ma éditer et postent dans le MessageBox – Ozzah

+0

i sera être modifier le code en question s'il vous plaît voir mon edit & je mettre cette déclaration, mais il n'y a pas exception exception, mais le fil arrête l'excution à cette déclaration pas plus loin & ce message sera afficher dans les locaux valeur de la variable _opcserver –