2

C# で生涯にわたって COM オブジェクトを使用する方法

OPC サーバー オブジェクトが作成され、それが threading.timer に使用されます。このタイマーは、opcserver オブジェクトが一定時間後に毎秒呼び出され、それ自体が "分離された COM オブジェクト" として例外を解放します。基になる RCW は使用できません.."

ここにコードがあります

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 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"]));
              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"]));
                    param.update1(rVals1, Convert.ToInt32(dt1["groupID"]));
                }

            }
        }
    }
    catch { }
    finally { }
}

適切な解決策を教えてください

4

1 に答える 1

0

OPC を使用しているときは、COM を使用しています。GUI も使用しているため、おそらくシングルスレッド アパートメント (STA) を使用していますApartmentState。この場合、OPC オブジェクトを最初にインスタンス化するスレッドで OPC 呼び出しがすべて発生するようにする必要があります。COM オブジェクトは STA スレッドで作成されるため、すべての呼び出しをそのスレッドにマーシャリングしようとします。

これを機能させるThreadには、 a ではなく別のを使用System.Threading.Timerして OPC 呼び出しを実行し、それらが常に同じスレッド上にあるようにする必要があります。コールバックは、System.Threading.Timer毎回 (非決定的) 別のスレッド (スレッド プールから) で実行されます。サーバーが応答しない場合は、UI スレッドからも離れたままにしておくと、パフォーマンスが向上します。UI が不足することになります。また、サーバーには、必要に応じて気まぐれに接続を閉じるオプションがあります。サーバーが切断を要求していることを知らせる OPC Shutdown イベントが発生します。

于 2011-05-19T03:54:04.373 に答える