Page 1 of 2 12 LastLast
Results 1 to 40 of 51

Thread: Problems with data exchange beatween forms

  1. #1

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Problems with data exchange beatween forms

    Hello all,

    I am trying to make an application, that gets data from OPC server to form1 and displays some pieces in form2. The app works that way: on start - form1 starts. Form2 must be started manually after form form1 is statrted (i mad a buttton for that). If some values in OPC server changes i need to see some of them in form2. Here is a sub which shows how do i get data from OPC server.
    Code:
    Public mObject As List (Of Object)
        Overridable Sub OnDataChange( _
        ByVal dwTransid As Integer, _
        ByVal hGroup As Integer, _
        ByVal hrMasterquality As Integer, _
        ByVal hrMastererror As Integer, _
        ByVal dwCount As Integer, _
        ByVal phClientItems() As Integer, _
        ByVal pvValues() As Object, _
        ByVal pwQualities() As Short, _
        ByVal pftTimeStamps() As OpcRcw.Da.FILETIME, _
        ByVal pErrors() As Integer) Implements IOPCDataCallback.OnDataChange
    
            Dim i As Integer = 0
            Dim j As Integer = 1
            Dim k As Integer = 0
    
            If dwCount > 0 Then
    
                mObject = New List(Of Object)
                For i = 0 To jk - 1
                    For j = 1 To jk
                        If phClientItems(i) = j Then
                            mObject.Add(pvValues(k))
                            k += 1
                        End If
                    Next j
                Next i
            End If
            dwCount = 0
        End Sub
    I have tried to write line before sub end
    Code:
    Dim c As Integer
    For c=0 To mObject.Count - 1
    Form2.mObject.Add(Object(c))
    Next c
    but nothing happened when i opened form2, nor on change of data in OPC server (i wrote the code that on form2 load all values are shown in msgbox, message box did not show up).

    dwCounts - how many values were changed in PLC.
    phClientItems - variable index.
    pvValues - variable value.

    All the ideas are wellcome.

    Thank you in advance.
    Last edited by Fact; Sep 9th, 2009 at 04:10 PM.

  2. #2
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,109

    Re: Problems with data exchange beatween forms

    That may do things you completely do not want, and there are several possible issues.

    1) Since you say Form2.whatever, that strongly suggests that you are using the default instance there. I thoroughly detest the default instance, as it causes more confusion than any possible benefit. I'm not quite sure what behavior you saw, but what the default instances may trip you up. Are you displaying the default instance of Form2, or are you displaying a different instance.

    2) You are passing around lots of reference types, such as when you add the object to the list from the array of object argument. That will copy the address of the item at the array index, but not the item itself. This could be correct, depending on how you are creating that array of object, but is that what you want to do? You then copy that address across to Form2. In that case, it probably will work, as the List is re-created each time the sub is run.
    My usual boring signature: Nothing

  3. #3

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Re: Problems with data exchange beatween forms

    Well, i am trying to do so that data from OPC server are populated in datagrid on form2. I do not have any problems with displaying data in datagrid on form1 :
    Code:
    Public mObject As List (Of Object)
        Overridable Sub OnDataChange( _
        ByVal dwTransid As Integer, _
        ByVal hGroup As Integer, _
        ByVal hrMasterquality As Integer, _
        ByVal hrMastererror As Integer, _
        ByVal dwCount As Integer, _
        ByVal phClientItems() As Integer, _
        ByVal pvValues() As Object, _
        ByVal pwQualities() As Short, _
        ByVal pftTimeStamps() As OpcRcw.Da.FILETIME, _
        ByVal pErrors() As Integer) Implements IOPCDataCallback.OnDataChange
    
            Dim i As Integer = 0
            Dim j As Integer = 1
            Dim k As Integer = 0
    
            If dwCount > 0 Then
    
                mObject = New List(Of Object)
                For i = 0 To jk - 1
                    For j = 1 To jk
                        If phClientItems(i) = j Then
                            DataGridView1.Rows(j-1).Cells(1).Value=Convert.ToString(pvValues(k))
                            mObject.Add(pvValues(k))
                            k += 1
                        End If
                    Next j
                Next i
            End If
            dwCount = 0
    But i need to do so that those values are displayed in form2 datagrid. I was thinking to make a public sub in form2, something like:
    Code:
    Public Sub xxx()
    Dim a As Integer
    For a=0 to jk
    DataGridView1.Rows(a).Cells(1).Value=Convert.TosString(mObject(i))
    Next a
    End Sub
    But then what? Or maybe the way i am trying to do it is not correct, i have no ideas.

  4. #4

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Re: Problems with data exchange beatween forms

    Well, just to be sure, that data comes i put a button on form2 and wrote code in its click event
    Code:
    Dim i As Integer
    
    For i=0 To Form1.mObject.Count - 1
    DataGridView1.Rows(i).Cells(1).Value=Form1.mObject(i)
    Next i
    and datagrid in form2 was filled with values from OPC server. How to make this code working without clicking of button? I can do it on form2 load, but it will work only on form2 loading.

  5. #5
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: Problems with data exchange beatween forms

    You dont want it to happen when the user clicks a button and you dont want it to happen when the form loads, so when do you want it to happen?
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  6. #6
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,109

    Re: Problems with data exchange beatween forms

    Is that OnDataChange running in a background thread?
    My usual boring signature: Nothing

  7. #7

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Re: Problems with data exchange beatween forms

    @chris128, this is a real time monitoring, i need to run that code for form2 when changes happens in OPC server.

    @Shaggy Hiker, i am not sure what means "running in background", but if data of an active item in active group changes, the server calls that sub OnDataChange().

  8. #8
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: Problems with data exchange beatween forms

    i need to run that code for form2 when changes happens in OPC server.
    Well then you need some way of knowing when changed happen in OPC server - which I assume is what this OnDataChange event that you mentioned is for. So stick the code in the event handler for that OnDataChange event.
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  9. #9

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Re: Problems with data exchange beatween forms

    Well chris, i might be do not express myself clear enough. When some changes in OPC server occours then OPC server calls that sub OnDataChange(). This sub by default looks like that:
    Code:
    Overridable Sub OnDataChange( _
        ByVal dwTransid As Integer, _
        ByVal hGroup As Integer, _
        ByVal hrMasterquality As Integer, _
        ByVal hrMastererror As Integer, _
        ByVal dwCount As Integer, _
        ByVal phClientItems() As Integer, _
        ByVal pvValues() As Object, _
        ByVal pwQualities() As Short, _
        ByVal pftTimeStamps() As OpcRcw.Da.FILETIME, _
        ByVal pErrors() As Integer) Implements IOPCDataCallback.OnDataChange
    
    End Sub
    So, inside that sub i put this code to take values from OPC server and populate them in forms1 datagrid.
    Code:
    Dim i As Integer = 0
            Dim j As Integer = 1
            Dim k As Integer = 0
    
            If dwCount > 0 Then
    
                mObject = New List(Of Object)
                For i = 0 To jk - 1
                    For j = 1 To jk
                        If phClientItems(i) = j Then
                            DataGridView1.Rows(j-1).Cells(1).Value=Convert.ToString(pvValues(k))
                            k += 1
                        End If
                    Next j
                Next i
            End If
    And each time some changes happens - values in forms1 datagrid changes as well (this sub is in form1). But i also want to see same chaneges in forms2 datagrid.
    This sub (OnDataChange) is a part of IOPCDataCallBack which i implement in form1 class.

  10. #10
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: Problems with data exchange beatween forms

    Then you need to tell form2 to do it as well - you could create a new method on Form2 called something like DataChanged and have that do the code that is required to fill Form2's datagrid, then in your OnDataChange sub on Form1 you call that DataChanged method on Form2.

    Personally I would try and implement this outside of your forms (ie in a dedicated class) but depending on how this OPC component works that may not be possible in this situation
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  11. #11

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Re: Problems with data exchange beatween forms

    Well, i am not good in VB so maybe this will help you more to undrstand what i am trying to do, and at that time i will try to create a new method and put its call into OnDataChange sub.
    Code:
    The basic sequence of the individual program steps corresponds to the previous sample
    OPC custom interface, asynchronous communication . These include establishing the
    connection to the OPC server, creating a group with variables, and reading and writing
    values for an item. The following table shows the steps to be executed by the program:
    Step Description
    1 Select .NET components
    2 Convert the ProgID to a CLSID
    3 Establish connection to the OPC server
    4 Create an OPC group
    5 Adding Items
    6 Request the interface IConnectionPointContainer
    7 Request the interface IOPCAsyncIO2
    8 Create callback object
    9 Connect OPC server and callback object of the client
    10 Execute required write and read operations
    11 Receive notifications of the OPC server
    12 Delete objects and release memory
    Step 1: Select .NET components
    To use the Custom Interface for OPC Data Access with .NET, you must use the Runtime
    Callable Wrapper (RCW) described above in your Visual Basic project. In the sample project,
    the components OpcRcw.Da and OpcRcw.Comn have already been added.
    If these do not appear in the selection, you can also select them using the Browse button
    from the following folder
    <installationpath>\SIEMENS\SIMATIC.NET\opc2\bin .
    Sample programs
    5.4 OPC Custom interface (asynchronous communication) in VB.NET
    Industrial Communication with PG/PC Volume 2 - Interfaces
    Programming Manual, Release 06/2008, C79000-G8976-C197-08 421
    Figure 5-25 Selecting the Runtime Callable Wrapper (RCW) in the Visual Basic project
    With the commands
    Imports OpcRcw.Comn
    Imports OpcRcw.Da
    it is simple to use the name space and methods of the OPC Custom interface with .NET
    Framework.
    Step 2: Convert the ProgID to a type
    To identify it, each COM server has a ProgID that is assigned to a worldwide unique type.
    This is obtained with the GetTypeFromProgID() function. The ProgID of the OPC server of
    SIMATIC NET is L"OPC.SimaticNET ":
    Dim typeofOPCserver As Type =
    Type.GetTypeFromProgID(L"OPC.SimaticNET")
    Step 3: Establish connection to the OPC server
    The CreateInstance() function of the Activator class generates an instance of the class with a
    previously specified type:
    m_server = Activator.CreateInstance(typeofOPCserver)
    The result of this section of program is an interface variable m_server of the type
    IOPCServer.
    Sample programs
    5.4 OPC Custom interface (asynchronous communication) in VB.NET
    Industrial Communication with PG/PC Volume 2 - Interfaces
    422 Programming Manual, Release 06/2008, C79000-G8976-C197-08
    Step 4: Create an OPC group
    The IOPCServer interface has the AddGroup() method for creating groups:
    m_server.AddGroup("MyOPCGroup",
    0,
    250,
    1,
    pTimeBias,
    pDeadband,
    LOCALE_ID,
    ServerGroup,
    RevisedUpdateRate,
    GetType(IOPCGroupStateMgt).GUID,
    m_group)
    The result of this program section is a group with the specified name and the required
    properties. AddGroup() also returns a variable m_group as return parameter, an interface to
    a group object, in this case IOPCGroupStateMgt. The IOPCGroupStateMgt interface is
    necessary to allow use of the SetState() methods. The SetState() method is required later to
    activate and deactivate a group.
    By means of a simple assignment, the m_item variable of the type IOPCItemMgt can be
    derived from the m_group interface variable.
    m_item = m_group
    Step 5: Adding Items
    The IOPCItemMgt interface has the AddItems() method for creating OPC items:
    m_item.AddItems(2, itemdefs, Results, pErrors)
    The result of this program section is that the server adds two items with the properties
    specified in the itemdefs parameter. The variables of the result structure Results (server
    handle, data type of the item on the target system etc.) are also initialized.
    Since the results are written to unmanaged memory by the underlying COM interface, the
    access from managed .NET code must make use of the marshaling functions:
    result = Marshal.PtrToStructure(pos, GetType(OPCITEMRESULT))
    ServerHandle1 = result.hServer
    pos = New IntPtr(pos.ToInt32() +
    Marshal.SizeOf(GetType(OPCITEMRESULT)))
    result = Marshal.PtrToStructure(pos, GetType(OPCITEMRESULT))
    ServerHandle2 = result.hServer
    The client must also make sure that the unmanaged memory is released:
    Marshal.FreeCoTaskMem(Results)
    Marshal.FreeCoTaskMem(pErrors)
    Step 6: Request the interface IConnectionPointContainer
    The m_ConnectionContainer variable of the type IConnectionPointContainer can be derived
    from the m_group variable.
    m_ConnectionContainer = m_group
    The interface is required to locate the IConnectionPoint interface.
    Sample programs
    5.4 OPC Custom interface (asynchronous communication) in VB.NET
    Industrial Communication with PG/PC Volume 2 - Interfaces
    Programming Manual, Release 06/2008, C79000-G8976-C197-08 423
    Step 7: Request the IOPCAsyncIO2 interfaces
    The m_asyncIO2 variable of the type IOPCAsyncIO2 can be derived from the m_group
    variable.
    m_asyncIO2 = m_group
    This interface provides methods for asynchronous reading and writing of values.
    Step 8: Create callback object
    To allow the OPC server to return a result of asynchronous operations, the
    IOPCDataCallback interface must be implemented on the client.
    Implements IOPCDataCallback
    The connection of the IConnectionPoint interface and IOPCDataCallback of the OPC server
    is established using the FindConnectionPoint() method of the IConnectionPointContainer
    interface. This generates a callback object for asynchronous calls.
    m_ConnectionContainer.FindConnectionPoint(
    GetType(IOPCDataCallback).GUID,
    m_ConnectionPoint)
    Step 9: Connect OPC server and callback object of the client
    The connection between the callback object of the OPC server and the client application is
    established by the Advise() method. The return variable m_dwCookie is an ID for the
    connection.
    m_ConnectionPoint.Advise(Me, m_dwCookie)
    Step 10: Execute required write or read operation
    The Read() and Write() methods that were generated in Step 7 can be accessed over the
    IOPCAsyncIO2 interface:
    m_asyncIO2.Read(1, pServer, Transaction, CancelID, pErrors)
    Step 11: Receive notifications of the OPC server
    If the data of an active item in an active group changes, the server calls the OnDataChange()
    method of the callback object. On completion of a read operation, the server calls the
    OnReadComplete() method, on completion of a write operation, the OnWriteComplete()
    method is called. The server passes the return values as parameters to the method.
    Overridable Sub OnDataChange(
    ByVal dwTransid As Integer,
    ByVal hGroup As Integer,
    ByVal hrMasterquality As Integer,
    ByVal hrMastererror As Integer,
    ByVal dwCount As Integer,
    ByVal phClientItems() As Integer,
    ByVal pvValues() As Object,
    ByVal pwQualities() As Short,
    ByVal pftTimeStamps() As OpcRcw.Da.FILETIME,
    ByVal pErrors() As Integer) Implements
    IOPCDataCallback.OnDataChange
    Sample programs
    5.5 OPC Custom interface (synchronous communication) in C#
    Industrial Communication with PG/PC Volume 2 - Interfaces
    424 Programming Manual, Release 06/2008, C79000-G8976-C197-08
    Step 12: Delete objects and release memory
    Before exiting the program, the OPC objects that have been created must be deleted and
    the memory reserved for them must be released. The relevant functions are integral parts of
    the previously used interfaces. Unadvise() terminates the connection between the OPC
    server and the callback object:
    m_ConnectionPoint.Unadvise(m_dwCookie)
    Marshal.ReleaseComObject(m_ConnectionPoint)
    m_item.RemoveItems(2, pItems, pErrors)
    ....
    Marshal.FreeCoTaskMem(pErrors)
    m_server.RemoveGroup(ServerGroup, True)
    Releasing memory
    When using COM, it is sometimes necessary for the client to release memory that was
    requested by the server. The rules for this are as follows:
    ● [out]: The memory for a parameter with this attribute will be requested from the server.
    ● [in, out]: The memory for such a parameter will be requested from the client. The server
    can release the memory again and reallocate it.
    ● [in]: The client will request the memory. The server is not responsible for releasing the
    memory.
    In all three cases, the reserved memory of unmanaged COM objects should be released by
    the client.
    Thank you for your patience

  12. #12

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Re: Problems with data exchange beatween forms

    OK, i made sub in form2:
    Code:
    Public sub xxx ( ByVal example as object)
    ListBox1.Items.Add(example)
    MsgBox(example)
    End Sub
    And changed code in forms1 OnDataChange sub:
    Code:
    Public mObject As List(Of Objects) = New List(Of  Objects)
    Overridable Sub OnDataChange( _
        ByVal dwTransid As Integer, _
        ByVal hGroup As Integer, _
        ByVal hrMasterquality As Integer, _
        ByVal hrMastererror As Integer, _
        ByVal dwCount As Integer, _
        ByVal phClientItems() As Integer, _
        ByVal pvValues() As Object, _
        ByVal pwQualities() As Short, _
        ByVal pftTimeStamps() As OpcRcw.Da.FILETIME, _
        ByVal pErrors() As Integer) Implements IOPCDataCallback.OnDataChange
    Try
    Dim i As Integer = 0
            Dim j As Integer = 1
            Dim k As Integer = 0
    
            If dwCount > 0 Then
    
                mObject = New List(Of Object)
                For i = 0 To jk - 1
                    For j = 1 To jk
                        If phClientItems(i) = j Then
                            DataGridView1.Rows(j-1).Cells(1).Value=Convert.ToString(pvValues(k))
                            mObject.Add(pvValues(k))
                            k += 1
                        End If
                    Next j
                Next i
            End If
    Finally
    Form2.xxx(mObject(0))
    End Try
    End Sub
    Each time when data changes in OPC server - forms1 datagrid gets new data, message box shows correct value, but my forms2 ListBox remains empty. Now i am really out of imagination.

  13. #13
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: Problems with data exchange beatween forms

    I notice you are using the default form instance there (as you just used Form2.xxx instead of creating a new instance of Form2 then calling xxx on that instance). Are you sure that the Form2 you are viewing on the screen is the default instance as well?

    Also, have you placed that call to Form2.xxx in the Finally block of your Try/Catch code just to test with? because I dont think it is going to give you the results you expect when it is only getting called once
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  14. #14

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Re: Problems with data exchange beatween forms

    Quote Originally Posted by chris128 View Post
    I notice you are using the default form instance there (as you just used Form2.xxx instead of creating a new instance of Form2 then calling xxx on that instance). Are you sure that the Form2 you are viewing on the screen is the default instance as well?
    Yes, i think so, code of form2
    Code:
    Option Strict Off
    Option Explicit On
    
    Imports System.IO
    
    
    Public Class Form2
        Public mObject As List(Of Object) = New List(Of Object)
    
    
        Private Sub Form2_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    
            DataGridView1.Columns(0).HeaderText = "Parameter"
            DataGridView1.Columns(1).HeaderText = "Value"
            DataGridView1.Columns(2).HeaderText = "Unit"
            Dim sr As StreamReader = New StreamReader("txt\viens.txt")
            Dim line As String = Nothing
            Do
                line = sr.ReadLine()
                If Not line = Nothing Then
                    Dim mArray(2) As String
                    mArray(0) = Split(line, "  ")(0)
                    mArray(1) = ""
                    mArray(2) = Split(line, "  ")(1)
                    DataGridView1.Rows.Add(mArray)
                End If
            Loop Until line Is Nothing
    
            Dim i As Integer
            For i = 0 To Form1.mObject.Count - 1
                DataGridView1.Rows(Form1.mObject1(i) - 1).Cells(1).Value = (Form1.mObject(i))
                ListBox1.Items.Add(Form1.mObject(i))
            Next i
        End Sub
    
        Public Sub xxx(ByVal example As String)
    
           ListBox1.Items.Add(example)
        End Sub
    End Class
    Quote Originally Posted by chris128 View Post
    Also, have you placed that call to Form2.xxx in the Finally block of your Try/Catch code just to test with? because I dont think it is going to give you the results you expect when it is only getting called once
    It looks silly, but i put it there as i do not know where else i could put it

  15. #15
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,109

    Re: Problems with data exchange beatween forms

    How are you displaying form 2? That would show us whether you are using the default instance or not.
    My usual boring signature: Nothing

  16. #16

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Re: Problems with data exchange beatween forms

    If you mean how do i open form2 then here is a code in form1:
    Code:
    Private Sub Form2ToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Form2ToolStripMenuItem.Click
            Form2.Show()
        End Sub

  17. #17
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,109

    Re: Problems with data exchange beatween forms

    Well, that's the default instance, so the sub call should be correct the way you have it.

    The problem would be if you had declared an instance of Form2 with something like:

    Private myFrm2 as New Form2

    I notice that you are putting together a list of objects in the data arrival method, but only passing over the first object, but then, you are also just adding one item, so it is probably nearly what you want to pass.

    However, since you are passing an object to a sub that is expecting a String, you probably have Option Strict Off. You may find that what is coming across is not at all what you expect to see.

    The next step would be to put a breakpoint in the sub on Form2 where you add the item to the listbox. If the breakpoint is reached, execution will pause, and you can look to see what is in the argument to the sub.

    After doing that, you will have these possibilities:

    1) The breakpoint is never reached.
    2) The breakpoint is reached, but the argument is an empty string.
    3) The breakpoint is reached, and the argument is not an empty string, but it is not what you wanted.
    4) The breakpoint is reached, and the argument is what you wanted.

    What to do next is dependent on which of those four is the right one.
    My usual boring signature: Nothing

  18. #18

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Re: Problems with data exchange beatween forms

    Well, i hope i did correctly what you said and when this line in form1
    Code:
    Form2.xxx(mObject(0))
    becomes highlighted (yellow) and the value of mObject(0) is the one that should be.

    EDITED:
    After that line becomes yellow and i press F10 form2 sub xxx becomes yellow and the value of variable example is the same as mObject(0), and after that it returns back to form1 line Form2.xxx(mObject(0)) that line becomes gray, but nothing is added to listbox.
    Last edited by Fact; Sep 11th, 2009 at 05:31 PM.

  19. #19
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,109

    Re: Problems with data exchange beatween forms

    That wasn't the line I wanted the breakpoint on. Put it on this line from the sub in Form2:

    ListBox1.Items.Add(example)

    Have no other breakpoints.

    From what you have said, it sounds like you will end up with situation 4. If that is the case, the one other thing that might be an easy answer would be to add the line:

    Listbox1.Refresh

    after the item is added.

    However, give that a try, and see whether example is, in fact, what you expect it to be.
    My usual boring signature: Nothing

  20. #20

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Re: Problems with data exchange beatween forms

    I did that but listbox is empty. After line ListBox1.Items.Add(exmple) i put line MsgBox(example) and the message box with correct value showed up.

  21. #21
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,109

    Re: Problems with data exchange beatween forms

    Ok, I think you have completely covered the fact that the listbox should be getting something, yet it is not displaying anything. This leads to one of a variety of possibilities.

    First off, try this:

    You have shown the Load event for Form2. Put something into the listbox during the load event. It doesn't matter what, just some random string will be fine. Does that show up?

    If that string does not show up, then you are seeing the wrong form. Why that is I can't say, as I see no reason for it from what you have shown. The most typical reason for that is because you are changing the default instance, but not showing the default instance. However, you showed how you are showing the form, and you are showing the default instance, as well, so that should not be the answer.

    If the string does show up, then I suspect that your data arrival is running in a background thread. I have never tried messing with that, but I seem to remember JM mentioning something about a control in a background thread not displaying in the UI thread. On the other hand, that doesn't seem right, either, as you are not creating the control in the background thread, so adding to it from a background thread should cause an IllegalCrossThread exception.

    Either way, I must say that I am stumped. From what you have shown so far, I see no good reason why the item is not showing up.
    My usual boring signature: Nothing

  22. #22

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Re: Problems with data exchange beatween forms

    OK, in form2 load event i put line ListBox1.Items.Add(Form1.mObjetc(0)) and i got into listbox first value from OPC server, and that is good.

  23. #23
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,109

    Re: Problems with data exchange beatween forms

    I think you may not be on the thread you think you are on. I don't have enough experience with this to be sure whether or not what you are seeing is a result of your call to the sub happening on a background thread, but I think it is reasonably likely.

    One alternative you might try would be something like what I do in post #2 of this thread using a SynchronizationContext:

    http://www.vbforums.com/showthread.p...zation+context

    Save the SynchronizationContext early on, when you are clearly in the UI thread, though it doesn't really matter where you save it, though it should probably be on Form1.

    Then, look at Posting a call to the SynchronizationContext that you saved. It's a pretty simple means of ensuring that your call is happening on the UI thread. It might solve your problem, or it might miss the mark.
    My usual boring signature: Nothing

  24. #24

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Re: Problems with data exchange beatween forms

    OK, thank you for being patience with me, Shaggy Hiker, +karma
    I will check the alternative you suggest.

  25. #25

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Re: Problems with data exchange beatween forms

    Well Shaggy Hiker, i have read your post, but as i am not good enough in visual basic i hardly can understand things there.
    Maybe somebody has more solutions what is wrong here?

  26. #26

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Re: Problems with data exchange beatween forms

    OK, i think i found what is wrong, but don't know how to fix.
    In form 2 i made a public sub
    Code:
    Public Sub xxx(ByRef example As Object)
    
            TextBox1.Text = Convert.ToString(example)
    
        End Sub
    And put a breake point at it.
    In form1, sub OnDataChange, after Try i put code
    Code:
    Form2.xxx(mObject(0))
    and put breake point at line Try.
    After debugger started program stopped on line Try in form1. On next line
    Code:
    Form2.xxx(mObject(0))
    i put mouse cursor on mOject(0) and saw that it contains value:
    Code:
    mObject Count=1
    (0)  45 {UInteger}
    After that line
    Code:
    Public Sub xxx(ByRef example As Object)
    in form2 became highlighted, and value of example is
    Code:
    example  45  {UInteger}
    Jump on line
    Code:
    TextBox1.Text = Convert.ToString(example)
    gave me
    Code:
    TextBox1.Text  ""
    exmple: 45  {UInteger}
    After jump to line End Sub, the values are
    Code:
    TextBox1.Text  "45"
    exmple: 45  {UInteger}
    Then it returned to form1 line
    Code:
    Form2.xxx(mObject(0))
    and the value of mObject(0) there is
    Code:
    mObject Count=1
    (0)  45 {UInteger}
    But i decided to check what value contains TextBox1 in form2, so went back to form2, put mouse pointer on the TextBox1.Text in line
    Code:
    TextBox1.Text = Convert.ToString(example)
    and saw:
    Code:
    TextBox.Text1 { "An exception 'Microsoft.VisualStudio.Debugger.Runtime.CrossThreadMessagingException' occurred"}
    StackTrace
    Code:
    StackTrace = "   at Microsoft.VisualStudio.Debugger.Runtime.Main.ThrowCrossThreadMessageException(String formatString)    at System.Windows.Forms.SafeNativeMethods.GetWindowTextLength(HandleRef hWnd)    at System.Windows.Forms.Control.get_WindowText()    at System.Windo...
    I believe that is the problem why textbox remains empty in form2. Does anybody has any clue how can i fix it?
    Last edited by Fact; Sep 12th, 2009 at 08:04 AM.

  27. #27
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: Problems with data exchange beatween forms

    It means you are accessing that control from a thread that does not 'own' it. Basically you should not modify any controls from a background thread, it should be done from the UI thread. You can use JMC's tutorial here to learn how to work around this: http://www.vbforums.com/showthread.php?t=498387
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  28. #28

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Re: Problems with data exchange beatween forms

    Well, i have tried that as well, but with no luck
    Form2
    Code:
    Public Delegate Sub SetTextBoxTextInvoker(ByVal text As String)
        Public Sub SetTextBoxText(ByVal text As String)
    
            If TextBox1.InvokeRequired Then
    
                TextBox1.Invoke(New SetTextBoxTextInvoker(AddressOf SetTextBoxText), text)
            Else
                TextBox1.Text = text
            End If
        End Sub
    Form1
    Code:
    Finally
                Form2.SetTextBoxText(mObject(0))
    End Try
    Is that code correct?

  29. #29
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: Problems with data exchange beatween forms

    I think that should work yes, but the way I have always done it in the past is to use two separate methods, so for example:

    vb Code:
    1. Public Sub SetTextBoxText(ByVal text As String)
    2.       TextBox1.Invoke(New SetTextBoxTextInvoker(AddressOf InvokedSetTextBoxText), text)
    3. End Sub
    4.  
    5. Private Sub InvokedSetTextBoxText(ByVal text As String)
    6.       TextBox1.Text = text
    7. End Sub

    Like I said though, I think the way you are currently doing it should still work...
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  30. #30

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Re: Problems with data exchange beatween forms

    Well, result is the same - empty textbox in form2. I even do not understand, why do i need this code
    Code:
    Public Delegate Sub SetTextBoxTextInvoker(ByVal text As String)
        Public Sub SetTextBoxText(ByVal text As String)
    
            If TextBox1.InvokeRequired Then
    
                TextBox1.Invoke(New SetTextBoxTextInvoker(AddressOf SetTextBoxText), text)
            Else
                TextBox1.Text = text
            End If
        End Sub
    i put a break point on this sub and saw that program comes to if and jumps to else, so it makes same as mine sub
    Code:
    Public Sub xxx(ByVal example As Object)
    
            TextBox1.Text = Convert.ToString(example)
    
        End Sub

  31. #31

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Re: Problems with data exchange beatween forms

    After long experiments i came up to the dead end. I decided to clean up that OnDataChange sub and simply put code that each time when something changes in OPC server i will get an message box, with a first value.
    Code:
    Overridable Sub OnDataChange( _
        ByVal dwTransid As Integer, _
        ByVal hGroup As Integer, _
        ByVal hrMasterquality As Integer, _
        ByVal hrMastererror As Integer, _
        ByVal dwCount As Integer, _
        ByVal phClientItems() As Integer, _
        ByVal pvValues() As Object, _
        ByVal pwQualities() As Short, _
        ByVal pftTimeStamps() As OpcRcw.Da.FILETIME, _
        ByVal pErrors() As Integer) Implements IOPCDataCallback.OnDataChange
    If dwCount > 0 Then
                MsgBox(pvValues(0))
            End If
            dwCount = 0
    
        End Sub
    So each time OPC server calls that sub i get a message box with the first value. After that i decided to make so that after each change i get value in the texbox that is on form1, but textbox remains empty all the time.
    Code:
    Overridable Sub OnDataChange( _
        ByVal dwTransid As Integer, _
        ByVal hGroup As Integer, _
        ByVal hrMasterquality As Integer, _
        ByVal hrMastererror As Integer, _
        ByVal dwCount As Integer, _
        ByVal phClientItems() As Integer, _
        ByVal pvValues() As Object, _
        ByVal pwQualities() As Short, _
        ByVal pftTimeStamps() As OpcRcw.Da.FILETIME, _
        ByVal pErrors() As Integer) Implements IOPCDataCallback.OnDataChange
    If dwCount > 0 Then
                MsgBox(pvValues(0))
                TextBox1.Text = Convert.ToString(pvValues(0))
            End If
            dwCount = 0
    
        End Sub
    I have checked what is wrong, and as Chris128 said it was
    Quote Originally Posted by chris128 View Post
    It means you are accessing that control from a thread that does not 'own' it.
    Fine, i put those two lines in my code and textbox on form1 started to work (same thing with ListBox, RichTextBox and so on).
    Code:
    Overridable Sub OnDataChange( _
        ByVal dwTransid As Integer, _
        ByVal hGroup As Integer, _
        ByVal hrMasterquality As Integer, _
        ByVal hrMastererror As Integer, _
        ByVal dwCount As Integer, _
        ByVal phClientItems() As Integer, _
        ByVal pvValues() As Object, _
        ByVal pwQualities() As Short, _
        ByVal pftTimeStamps() As OpcRcw.Da.FILETIME, _
        ByVal pErrors() As Integer) Implements IOPCDataCallback.OnDataChange
    If dwCount > 0 Then
                MsgBox(pvValues(0))
                ThreadExceptionDialog.CheckForIllegalCrossThreadCalls = False
                TextBox1.Text = Convert.ToString(pvValues(0))
                ThreadExceptionDialog.CheckForIllegalCrossThreadCalls = True
            End If
            dwCount = 0
        End Sub
    It would be good, but how then i can make to work textbox on form2?
    Beg for ideas, or my head will explode

  32. #32
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: Problems with data exchange beatween forms

    All you are doing there is just hiding the exceptions by setting CheckForIllegalCrossThreadCalls to false... Those exceptions are thrown for a reason, just hiding them instead of actually fixing the problem is going to cause you more problems in the future
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  33. #33

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Re: Problems with data exchange beatween forms

    OK, i made things like that
    Code:
    Form1
    Private Delegate Sub yyyInvoker(ByVal mString As String)
        Private Sub yyy(ByVal mString As String)
            If TextBox1.InvokeRequired Then
                TextBox1.Invoke(New yyyInvoker(AddressOf yyy), mString)
            Else
                TextBox1.Text = mString
            End If
        End Sub
     Overridable Sub OnDataChange(...........................)
            If dwCount > 0 Then
                yyy(pvValues(0))
            End If
            dwCount = 0
        End Sub
    When the program comes to line
    Code:
    If TextBox1.InvokeRequired Then
    I see
    Code:
    TextBox1.InvokeRequired True
    and textbox in form1 is filled with a value from OPC server, HYRRAY!
    So i made similar sub in form2
    Code:
    Form2
    Public Delegate Sub xxxInvoker(ByVal qString As String)
        Public Sub xxx(ByVal qString As String)
            If TextBox1.InvokeRequired Then
                TextBox1.Invoke(New xxxInvoker(AddressOf xxx), qString)
            Else
                TextBox1.Text = qString
            End If
        End Sub
    and put a call into form1
    Code:
    Form1
    Overridable Sub OnDataChange(...........................)
    If dwCount > 0 Then
                yyy(pvValues(0))
                Form2.xxx(pvValues(0))
            End If
            dwCount = 0
        End Sub
    when program comes to line in form2
    Code:
    If TextBox1.InvokeRequired Then
    i see that
    Code:
    TextBox1.InvokeRequired  False
    and textbox in form2 remains empty.
    Any comments on that?

  34. #34
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: Problems with data exchange beatween forms

    Hmm that does sound odd - is there any chance you could post your full solution here as an attachment to your post?
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  35. #35

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Re: Problems with data exchange beatween forms

    Yes sure, here it is, the strange thing is that it says, that invokerequired False.
    Maybe it is not possible to do what i want.
    Last edited by Fact; Sep 16th, 2009 at 01:07 AM.

  36. #36
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: Problems with data exchange beatween forms

    Firstly, turn Option Strict on!

    Anyway - I'll take a look through your code now and see if I can see anything
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  37. #37

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Re: Problems with data exchange beatween forms

    In the SIEMENS sample it is shown as Strict off.

  38. #38
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: Problems with data exchange beatween forms

    Then they are not very good VB.NET programmers... There is no good reason to have Option Strict off, it just means you have a little bit less to type and can be less careful with casting and converting, which then results in problems a lot of the time. Turn it on and fix all of the problems that it highlights and then see if you are still having problems.
    I looked at your code but at the moment it is so messy (presumably from you trying out lots of different things) that it is quite hard to see what is going on. Also, I do not know what this OPC thing does or how the OnDataChanged method gets called so it is hard for me to test it. I tested just calling that OnDataChanged method from a button click and passing in some random parameters but it all worked fine and the textbox on both Form1 and Form2 was filled in.
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  39. #39

    Thread Starter
    Member
    Join Date
    Sep 2009
    Posts
    32

    Re: Problems with data exchange beatween forms

    Well chris128, you did a great job, i am really appreciate that!

    Quote Originally Posted by chris128 View Post
    Then they are not very good VB.NET programmers...
    Unfortunetaly i am much worser then they are, that is fact

    Here is a piece of information how this OnDataChange works, maybe it will be usefull for you in some future
    Code:
    To allow the OPC server to return a result of asynchronous operations, the
    IOPCDataCallback interface must be implemented on the client.
    Implements IOPCDataCallback
    The connection of the IConnectionPoint interface and IOPCDataCallback of the OPC server
    is established using the FindConnectionPoint() method of the IConnectionPointContainer
    interface. This generates a callback object for asynchronous calls.
    m_ConnectionContainer.FindConnectionPoint(
    GetType(IOPCDataCallback).GUID,
    m_ConnectionPoint)
    The connection between the callback object of the OPC server and the client application is
    established by the Advise() method. The return variable m_dwCookie is an ID for the
    connection.
    m_ConnectionPoint.Advise(Me, m_dwCookie)
    method of the callback object. On completion of a read operation, the server calls the
    OnReadComplete() method, on completion of a write operation, the OnWriteComplete()
    method is called. The server passes the return values as parameters to the method.
    Overridable Sub OnDataChange(
    ByVal dwTransid As Integer,
    ByVal hGroup As Integer,
    ByVal hrMasterquality As Integer,
    ByVal hrMastererror As Integer,
    ByVal dwCount As Integer,
    ByVal phClientItems() As Integer,
    ByVal pvValues() As Object,
    ByVal pwQualities() As Short,
    ByVal pftTimeStamps() As OpcRcw.Da.FILETIME,
    ByVal pErrors() As Integer) Implements
    IOPCDataCallback.OnDataChange
    I will try to start it all fom the empty list, if i succeed i will post the result, if not - well, then i will be in need to give up.
    Here is a small gift from me

    Once more time thank you very much for all you did.

  40. #40
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: Problems with data exchange beatween forms

    haha thank you for the massively oversized beer

    What exactly does this OPC server thing do? I mean is there any way I could test it in the same way you are testing it? Does it require any special equipment or anything like that?
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width