COM对象长期使用

发布于 2024-11-03 03:53:29 字数 7181 浏览 5 评论 0原文

如何在C#中使用COM对象的生命周期

我将创建OPC服务器对象,它将被用于threading.timer这个计时器将在opcserver对象经过一段时间后每隔几秒被调用一次,它将释放自己的鞋异常为“无法使用已与其底层 RCW 分离的 COM 对象。”

这是代码,

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 { }
}

请告诉我正确的解决方案

how to used the COM object for the lifetime in C#

I will be created the OPC server object, it will be used into the threading.timer this timer will be invoked at every seconds after the some time opcserver object, it will be release itself shoe the exception as " COM object that has been separated from its underlying RCW cannot be used.."

Here is the code

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 { }
}

please tell me the proper solution

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

挽清梦 2024-11-10 03:53:29

当您使用 OPC 时,您就是在使用 COM。由于您也在使用 GUI,因此您很可能在 ApartmentState 中使用单线程单元 (STA)。在这种情况下,您应该确保 OPC 调用全部发生在首先实例化 OPC 对象的线程上。由于 COM 对象是在 STA 线程上创建的,因此它将尝试将所有调用封送回该线程。

要实现此功能,您需要使用单独的 Thread 而不是 System.Threading.Timer 来执行 OPC 调用,以便它们始终位于同一线程上。 System.Threading.Timer 回调每次都会在不同的线程(来自线程池)上执行(不确定)。如果服务器不响应,您将获得更好的性能,使其远离 UI 线程,您将在 UI 中出现缺失。此外,服务器可以根据需要选择关闭连接。您将收到一个 OPC 关闭事件,告诉您服务器希望您断开连接。

When you are using OPC, you are using COM. Since you are also using a GUI, you are most likely using Single-Threaded Apartment (STA) for your ApartmentState. When this is the case, you should make sure that the OPC calls all happen on the thread that first instantiates the OPC object. Since the COM object is created on an STA thread, then it will try to marshal all the calls back onto that thread.

To make this work, you'll need to use a separate Thread instead of a System.Threading.Timer to do the OPC calls so that they are always on the same thread. The System.Threading.Timer callback will execute on a different thread (from the thread pool) every time (non-deterministic). You'll get better performance keeping it off the UI thread too, if the server is not responding, you'll get lack in the UI. Also, the server has the option of closing connections on a whim if it wants. You'll get an OPC Shutdown event that will tell you the server wants you to disconnect.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文