ActiveX / Threads question

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • AnalogKid

    #1

    ActiveX / Threads question

    Short question:
    What's the difference between SingleUse and MultiUse ?

    Long question:
    I've been writing some sample code to see how different Instancing
    values and threading models work. I tried all main combinations of
    Instancing (Multiuse/Singleuse) and of Threading models (per
    object/pool). Here's what I found:

    MultiUse - Thread per Object
    One new object for each request

    SingleUse - Thread per Object
    One new object for each request

    MultiUse - Thread Pool (w/ 1 thread)
    One object reused by all requests

    SingleUse - Thread Pool (w/ 1 thread)
    One new object for each request

    The SU seems to be 100% superfluous: not only changing thread model
    does not change the way it works, but whatever it does, it's exaclty
    what MU does!

    In order to test, I have created an ActiveXEXE with a form (frmTest)
    and two classes (instancing is MU for one and SU for the other), both
    have the same public method:

    Public Sub Show(ByVal FormCaption As String, Top As Long, Left As
    Long)
    With frmTest
    'First time show
    If Not .Visible Then
    .Top = Top
    .Left = Left
    .Visible = True
    DoEvents
    End If
    .Caption = .Caption & FormCaption
    End With
    End Sub

    The client calls this with something like:

    Dim MUServ As New ActiveXServerEX E.MultiUseClass
    Call MUServ.Show(Ind ex & " - " & Time, Top, Left + Width)

    [Don't worry about the Top/Left stuff, it's irrelevant for this
    discussion]

    Can anybody shed some light on this topic once and for all ?

    Thanks!
    AK


  • Steve Gerrard

    #2
    Re: ActiveX / Threads question


    "AnalogKid" <AnalogKid17@(m ore_than_warm)m ail.com> wrote in message
    news:mqmag09dak f57hapvbaihd97s 2uvat6j5c@4ax.c om...
    | Short question:
    | What's the difference between SingleUse and MultiUse ?
    |
    | Long question:
    | I've been writing some sample code to see how different Instancing
    | values and threading models work. I tried all main combinations of
    | Instancing (Multiuse/Singleuse) and of Threading models (per
    | object/pool). Here's what I found:
    |
    | MultiUse - Thread per Object
    | One new object for each request

    Each object is created by the same instance of the activex.exe. If there
    is a module in the activex.exe with public data, all of the objects
    could see that data, even if they are created by different applications.
    Each object has its own thread.

    |
    | SingleUse - Thread per Object
    | One new object for each request
    |


    Each object is created by a new instance of the activex.exe. Each object
    can see public data only in its own instance of the activex.exe. Each
    object has its own thread (actually, each has its own process).

    | MultiUse - Thread Pool (w/ 1 thread)
    | One object reused by all requests
    |

    Not quite. Actually nearly the same as MultiUse Thread/Object, except
    that all the objects will be serviced using the same thread. You can
    still create multiple, discreet objects.

    | SingleUse - Thread Pool (w/ 1 thread)
    | One new object for each request
    |
    |"changing thread model does not change the way it works"

    Correct. The threading option applies only to MultiUse, not to
    SingleUse, so this is identical to SingleUse - Thread/Object.

    Clear as mud? :-)


    Comment

    • AnalogKid

      #3
      Re: ActiveX / Threads question

      On Mon, 26 Jul 2004 18:45:39 -0700, "Steve Gerrard"
      <notstevegerrar d@comcast.net> wrote:
      [color=blue]
      >
      >"AnalogKid" <AnalogKid17@(m ore_than_warm)m ail.com> wrote in message
      >news:mqmag09da kf57hapvbaihd97 s2uvat6j5c@4ax. com...
      >| Short question:
      >| What's the difference between SingleUse and MultiUse ?
      >|
      >| Long question:
      >| I've been writing some sample code to see how different Instancing
      >| values and threading models work. I tried all main combinations of
      >| Instancing (Multiuse/Singleuse) and of Threading models (per
      >| object/pool). Here's what I found:
      >|
      >| MultiUse - Thread per Object
      >| One new object for each request
      >
      >Each object is created by the same instance of the activex.exe. If there
      >is a module in the activex.exe with public data, all of the objects
      >could see that data, even if they are created by different applications.
      >Each object has its own thread.
      >[/color]

      Would you be kind enough to post some sample code to prove this ? I
      modified my code to read/write a public property and each object
      created has its own copy. When you say public data I assume you meana
      public property in the MultiUse class, correct ?
      [color=blue]
      >|
      >| SingleUse - Thread per Object
      >| One new object for each request
      >|
      >
      >
      >Each object is created by a new instance of the activex.exe. Each object
      >can see public data only in its own instance of the activex.exe. Each
      >object has its own thread (actually, each has its own process).
      >[/color]

      Again, I get the same result. No shared data.
      [color=blue]
      >| MultiUse - Thread Pool (w/ 1 thread)
      >| One object reused by all requests
      >|
      >
      >Not quite. Actually nearly the same as MultiUse Thread/Object, except
      >that all the objects will be serviced using the same thread. You can
      >still create multiple, discreet objects.
      >
      >| SingleUse - Thread Pool (w/ 1 thread)
      >| One new object for each request
      >|
      >|"changing thread model does not change the way it works"
      >
      >Correct. The threading option applies only to MultiUse, not to
      >SingleUse, so this is identical to SingleUse - Thread/Object.
      >
      >Clear as mud? :-)
      >[/color]
      Thank you for trying to explain this to me, I beg you not to give
      up... I think part of the problem is in terminology. The way I see it
      there is 1 ActiveX that contains n Classes. Each class can be
      instantiated x times to create x copies of itself (objects).

      On top of this you talk about instances of the ActiveX, do you mean
      instance of one of the ActiveX Classes ?

      Thanks
      AK

      PS: I haven't even asked questions about Apartment and Single threaded
      in DLLs yet... Hopefully that will be easier once EXEs are assimiltaed
      :-)

      Comment

      • Steve Gerrard

        #4
        Re: ActiveX / Threads question


        "AnalogKid" <AnalogKid17@(m ore_than_warm)m ail.com> wrote in message
        news:9nifg0d2u9 f0ga2i51m6dn00b clegv38c9@4ax.c om...
        | On Mon, 26 Jul 2004 18:45:39 -0700, "Steve Gerrard"
        | <notstevegerrar d@comcast.net> wrote:
        |
        | >| MultiUse - Thread per Object
        | >
        | >Each object is created by the same instance of the activex.exe. If
        there
        | >is a module in the activex.exe with public data, all of the objects
        | >could see that data, even if they are created by different
        applications.
        | >Each object has its own thread.
        | >
        |
        | Would you be kind enough to post some sample code to prove this ? I
        | modified my code to read/write a public property and each object
        | created has its own copy. When you say public data I assume you meana
        | public property in the MultiUse class, correct ?
        |

        No, by public data I mean in a bas module. Each object instance will
        have its own class data, but they can retrieve a "shared" value from the
        bas module.

        Add this to your activex.exe, and set its project startup property to
        sub main:

        Public globalStart As Single

        Public Sub Main()
        globalStart = Timer
        End Sub

        Then put a public property in your class, along with what you have, like
        this:
        Public Property GetStart() As Single
        GetStart = globalStart
        End Property

        In your test code, you should be able to see that each object instance
        has its own class data, but they all return the same value for GetStart.
        It will help if you delay 1 or two seconds between each object creation,
        and don't discard any till the test is over. If you look at the process
        list in Task Manager while several objects are still alive, you should
        see only one copy of your activex.exe loaded.

        | >|
        | >| SingleUse - Thread per Object
        |
        | >Each object is created by a new instance of the activex.exe. Each
        object
        | >can see public data only in its own instance of the activex.exe. Each
        | >object has its own thread (actually, each has its own process).
        | >
        |
        | Again, I get the same result. No shared data.

        If you do the same thing with this activex.exe, you should discover that
        with SingleUse, each object instance has its own class data, but now
        each returns a different value for GetStart. If you look at the process
        list in Task Manager while several objects are still alive, you should
        see that several copies of your activex.exe are loaded.

        | Thank you for trying to explain this to me, I beg you not to give
        | up... I think part of the problem is in terminology. The way I see it
        | there is 1 ActiveX that contains n Classes. Each class can be
        | instantiated x times to create x copies of itself (objects).
        |
        | On top of this you talk about instances of the ActiveX, do you mean
        | instance of one of the ActiveX Classes ?
        |

        Multiple instance of an activex.exe: in task manager, multiple copies of
        the exe are loaded in the process list. This is similar to starting up
        several copies of Excel or some other program.

        Note that threading has nothing to do with instances of objects, or
        instances(copie s) of the activex.exe getting loaded. Threading is just
        about how multiple objects created from a multiuse class do their work -
        either by sharing one or more threads, or by each having its own thread
        assigned.


        Comment

        • AnalogKid

          #5
          Re: ActiveX / Threads question

          On Wed, 28 Jul 2004 19:10:31 -0700, "Steve Gerrard"
          <notstevegerrar d@comcast.net> wrote:

          Thanks for your reply, see mine below...[color=blue]
          >
          >"AnalogKid" <AnalogKid17@(m ore_than_warm)m ail.com> wrote in message
          >news:9nifg0d2u 9f0ga2i51m6dn00 bclegv38c9@4ax. com...
          >| On Mon, 26 Jul 2004 18:45:39 -0700, "Steve Gerrard"
          >| <notstevegerrar d@comcast.net> wrote:
          >|
          >| >| MultiUse - Thread per Object
          >| >
          >| >Each object is created by the same instance of the activex.exe. If there
          >| >is a module in the activex.exe with public data, all of the objects
          >| >could see that data, even if they are created by different aapplications.
          >| >Each object has its own thread.
          >| >
          >|
          >| Would you be kind enough to post some sample code to prove this ? I
          >| modified my code to read/write a public property and each object
          >| created has its own copy. When you say public data I assume you meana
          >| public property in the MultiUse class, correct ?
          >|
          >
          >No, by public data I mean in a bas module. Each object instance will
          >have its own class data, but they can retrieve a "shared" value from the
          >bas module.
          >
          >Add this to your activex.exe, and set its project startup property to
          >sub main:
          >
          >Public globalStart As Single
          >
          >Public Sub Main()
          > globalStart = Timer
          >End Sub
          >
          >Then put a public property in your class, along with what you have, like
          >this:
          >Public Property GetStart() As Single
          > GetStart = globalStart
          >End Property
          >
          >In your test code, you should be able to see that each object instance
          >has its own class data, but they all return the same value for GetStart.
          >It will help if you delay 1 or two seconds between each object creation,
          >and don't discard any till the test is over. If you look at the process
          >list in Task Manager while several objects are still alive, you should
          >see only one copy of your activex.exe loaded.
          >[/color]
          Steve, I had done a similar test, and while I correctly see one
          instance of the MU server and multiple of the SU server in the
          processes, I still see one copy of the public data per client, ie each
          has its own GetStart value!
          [color=blue]
          >| >|
          >| >| SingleUse - Thread per Object
          >|
          >| >Each object is created by a new instance of the activex.exe. Each object
          >| >can see public data only in its own instance of the activex.exe. Each
          >| >object has its own thread (actually, each has its own process).
          >| >
          >|
          >| Again, I get the same result. No shared data.
          >
          >If you do the same thing with this activex.exe, you should discover that
          >with SingleUse, each object instance has its own class data, but now
          >each returns a different value for GetStart. If you look at the process
          >list in Task Manager while several objects are still alive, you should
          >see that several copies of your activex.exe are loaded.
          >
          >| Thank you for trying to explain this to me, I beg you not to give
          >| up... I think part of the problem is in terminology. The way I see it
          >| there is 1 ActiveX that contains n Classes. Each class can be
          >| instantiated x times to create x copies of itself (objects).
          >|
          >| On top of this you talk about instances of the ActiveX, do you mean
          >| instance of one of the ActiveX Classes ?
          >|
          >
          >Multiple instance of an activex.exe: in task manager, multiple copies of
          >the exe are loaded in the process list. This is similar to starting up
          >several copies of Excel or some other program.
          >
          >Note that threading has nothing to do with instances of objects, or
          >instances(copi es) of the activex.exe getting loaded. Threading is just
          >about how multiple objects created from a multiuse class do their work -
          >either by sharing one or more threads, or by each having its own thread
          >assigned.
          >[/color]
          This is also hard to prove with test code: both "Thread per Object"
          and "Thread Pool" lock creation of new objects when one is busy.

          Thanks again for your help!

          Comment

          • Steve Gerrard

            #6
            Re: ActiveX / Threads question


            "AnalogKid" <AnalogKid17@(m ore_than_warm)m ail.com> wrote in message
            news:ionig0d1vs 1oi9cf6q300u5ti hp8ge7fm9@4ax.c om...
            | On Wed, 28 Jul 2004 19:10:31 -0700, "Steve Gerrard"
            | <notstevegerrar d@comcast.net> wrote:
            |
            | >
            | >Add this to your activex.exe, and set its project startup property to
            | >sub main:
            | >
            | >Public globalStart As Single
            | >
            | >Public Sub Main()
            | > globalStart = Timer
            | >End Sub
            | >

            The above must be in a .bas module, not in a class definition.

            | >Then put a public property in your class, along with what you have,
            like
            | >this:
            | >Public Property GetStart() As Single
            | > GetStart = globalStart
            | >End Property
            | >
            | >In your test code, you should be able to see that each object
            instance
            | >has its own class data, but they all return the same value for
            GetStart.
            | >It will help if you delay 1 or two seconds between each object
            creation,
            | >and don't discard any till the test is over. If you look at the
            process
            | >list in Task Manager while several objects are still alive, you
            should
            | >see only one copy of your activex.exe loaded.
            | >
            | Steve, I had done a similar test, and while I correctly see one
            | instance of the MU server and multiple of the SU server in the
            | processes, I still see one copy of the public data per client, ie each
            | has its own GetStart value!
            |

            I know for a fact this works for a MultiUse class, so you must have
            something wrong. Was the public data you checked stored in a .bas
            module, not a class?


            Comment

            • AnalogKid

              #7
              Re: ActiveX / Threads question

              Steve,
              Sorry for the interruption (short vacation...) I think I undesrstood
              at least part of the problem. See below:

              On Thu, 29 Jul 2004 18:42:04 -0700, "Steve Gerrard"
              <notstevegerrar d@comcast.net> wrote:
              [color=blue]
              >| >
              >| Steve, I had done a similar test, and while I correctly see one
              >| instance of the MU server and multiple of the SU server in the
              >| processes, I still see one copy of the public data per client, ie each
              >| has its own GetStart value!
              >|
              >I know for a fact this works for a MultiUse class, so you must have
              >something wrong. Was the public data you checked stored in a .bas
              >module, not a class?
              >[/color]
              The problem is that my Threading Model was set on Thread per Object,
              as opposed to the default, Thread Pool 1. Now I can see one copy of
              global data for all instantiations.

              This means that sharing the same global data is actually a matter of
              threads, it's not a prerogative of *all* MultiUse classes, but only
              when all clients communicate on the same thread (ie, Thread Pool w/ 1
              thread). As soon as you have multiple threads or Threads per Object
              (my previous test environment), even global data is duplicated for
              each new object created.

              Now that we have determined this, my reviewed summary of permutations
              looks like this:

              MultiUse - Thread per Object
              1 process in TaskManager
              One new object for each request (each w/ its own data)

              SingleUse - Thread per Object
              Multiple processes in TaskManager
              One new object for each request (each w/ its own data)

              MultiUse - Thread Pool (w/ 1 thread)
              1 process in TaskManager
              One object reused by all requests (global data is in common)

              SingleUse - Thread Pool (w/ 1 thread)
              Multiple processes in TaskManager
              One new object for each request (each w/ its own data)

              In conclusion:
              a) For SingleUse the Thread Model box should be grayed out, being able
              to choose between TpO and TP is just useless confusion. Even with
              Thread Pool 1, all created objects work on different threads.
              b) MultiUse with a 1 thread pool allows to share global data
              c) MultiUse with TpO is like SingleUse, except that there is always
              one process for MUs while SUs create one every time a class is
              instantiated.

              Hopefully the above is correct... can anybody confirm ?

              Many thanks to Steve!
              AK

              Comment

              • Steve Gerrard

                #8
                Re: ActiveX / Threads question

                comments in line:

                "AnalogKid" <AnalogKid17@(m ore_than_warm)m ail.com> wrote in message
                news:pna2h0516l sp4u9ja43l8c1q4 d8c9lncm3@4ax.c om...
                | Steve,
                | Sorry for the interruption (short vacation...) I think I undesrstood
                | at least part of the problem. See below:

                I'm doing one next week. I believe all vacations turn out to be short.
                :)

                | Now that we have determined this, my reviewed summary of permutations
                | looks like this:

                In all of the below, your use of the word object is confusing. An object
                is an instance of a class, which is distinct from an instance of the
                ..exe in task manager. In all of the below, you get a new object for each
                request, never the same object.

                | MultiUse - Thread per Object
                | 1 process in TaskManager
                | One new object for each request (each w/ its own data)

                I confirm this. It seems a little suprising, but there is no shared
                global data in this case, even though there is only one instance of the
                ..exe loaded.

                | SingleUse - Thread per Object
                | Multiple processes in TaskManager
                | One new object for each request (each w/ its own data)

                And no global data in common. Each object comes from a different .exe
                instance in task manager.

                | MultiUse - Thread Pool (w/ 1 thread)
                | 1 process in TaskManager
                | One object reused by all requests (global data is in common)

                Thats the language I don't like. Each object is still a distinct object,
                with its own class data. Only the global data that is not part of a
                class is common to them.

                | SingleUse - Thread Pool (w/ 1 thread)
                | Multiple processes in TaskManager
                | One new object for each request (each w/ its own data)

                Yup. SingleUse is SingleUse .

                | In conclusion:

                | a) For SingleUse the Thread Model box should be grayed out, being able
                | to choose between TpO and TP is just useless confusion. Even with
                | Thread Pool 1, all created objects work on different threads.

                Correct. At least it is documented as such. The only reason I can see
                for it is that the threading model applies to the whole project, and it
                is possible to have both SingleUse and MultiUse classes in the same exe.
                Figuring out what happens with that can be your next project. :)

                | b) MultiUse with a 1 thread pool allows to share global data

                Right.

                | c) MultiUse with TpO is like SingleUse, except that there is always
                | one process for MUs while SUs create one every time a class is
                | instantiated.
                |

                That seems to be right, odd as it is. Why would you go with SU, if
                MU+TPO gets you the same isolation with less loading up of duplicate
                exes?


                Comment

                • AnalogKid

                  #9
                  Re: ActiveX / Threads question

                  On Wed, 4 Aug 2004 20:05:34 -0700, "Steve Gerrard"
                  <mynamehere@com cast.net> wrote:
                  [color=blue]
                  >comments in line:
                  >
                  >"AnalogKid" <AnalogKid17@(m ore_than_warm)m ail.com> wrote in message
                  >news:pna2h0516 lsp4u9ja43l8c1q 4d8c9lncm3@4ax. com...
                  >| Steve,
                  >| Sorry for the interruption (short vacation...) I think I undesrstood
                  >| at least part of the problem. See below:
                  >
                  >I'm doing one next week. I believe all vacations turn out to be short.
                  >:)
                  >
                  >| Now that we have determined this, my reviewed summary of permutations
                  >| looks like this:
                  >
                  >In all of the below, your use of the word object is confusing. An object
                  >is an instance of a class, which is distinct from an instance of the
                  >.exe in task manager. In all of the below, you get a new object for each
                  >request, never the same object.
                  >
                  >| MultiUse - Thread per Object
                  >| 1 process in TaskManager
                  >| One new object for each request (each w/ its own data)
                  >
                  >I confirm this. It seems a little suprising, but there is no shared
                  >global data in this case, even though there is only one instance of the
                  >.exe loaded.
                  >
                  >| SingleUse - Thread per Object
                  >| Multiple processes in TaskManager
                  >| One new object for each request (each w/ its own data)
                  >
                  >And no global data in common. Each object comes from a different .exe
                  >instance in task manager.
                  >
                  >| MultiUse - Thread Pool (w/ 1 thread)
                  >| 1 process in TaskManager
                  >| One object reused by all requests (global data is in common)
                  >
                  >Thats the language I don't like. Each object is still a distinct object,
                  >with its own class data. Only the global data that is not part of a
                  >class is common to them.
                  >[/color]
                  Actually my language was correct; my understanding was wrong, though.
                  I was actually under the impression that all objects created would
                  point to the same one, but I see now that they are all distinct ones.
                  [color=blue]
                  >| SingleUse - Thread Pool (w/ 1 thread)
                  >| Multiple processes in TaskManager
                  >| One new object for each request (each w/ its own data)
                  >
                  >Yup. SingleUse is SingleUse .
                  >
                  >| In conclusion:
                  >
                  >| a) For SingleUse the Thread Model box should be grayed out, being able
                  >| to choose between TpO and TP is just useless confusion. Even with
                  >| Thread Pool 1, all created objects work on different threads.
                  >
                  >Correct. At least it is documented as such. The only reason I can see
                  >for it is that the threading model applies to the whole project, and it
                  >is possible to have both SingleUse and MultiUse classes in the same exe.
                  >Figuring out what happens with that can be your next project. :)
                  >
                  >| b) MultiUse with a 1 thread pool allows to share global data
                  >
                  >Right.
                  >
                  >| c) MultiUse with TpO is like SingleUse, except that there is always
                  >| one process for MUs while SUs create one every time a class is
                  >| instantiated.
                  >|
                  >
                  >That seems to be right, odd as it is. Why would you go with SU, if
                  >MU+TPO gets you the same isolation with less loading up of duplicate
                  >exes?
                  >[/color]

                  Comment

                  Working...