Control.Invoke and ref parameter

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

    Control.Invoke and ref parameter

    Hi,

    Does anyone know how Control.Invoke can invoke a method which has ref
    parameters?

    For example,

    class A {
    public delegate MyFuncHandler(r ef int i, ref int j);

    public void MyFunc(ref int i, ref int j)
    {
    ..
    }

    public A

    public void MyCaller(DataGr idView oDataGridView)
    {
    int x = 1;
    int y = 1;

    ...

    oDataGridView.I nvoke(new MyHandler(MyFun c), new object { ref x, ref y });

    ....
    }

    oDataGridView.I nvoke(new MyHandler(MyFun c), new object { ref x, ref y });

    produces compilation error. Am I doing this wrong, or Control.Invoke does
    not allow method with ref parameters?

    Thanks,



    --
    George
  • Barry Kelly

    #2
    Re: Control.Invoke and ref parameter

    George <wave@nospam.no spam> wrote:
    [color=blue]
    > Does anyone know how Control.Invoke can invoke a method which has ref
    > parameters?[/color]
    [color=blue]
    > oDataGridView.I nvoke(new MyHandler(MyFun c), new object { ref x, ref y });[/color]

    instead use:

    object[] args = { x, y };
    oDataGridView.I nvoke(new MyHandler(MyFun c), args);
    // use args[0] (returned value of x)
    // use args[1] (returned value of y)

    Now, args will have been modified based on what MyFunc did to x and y.

    -- Barry

    --

    Comment

    • George

      #3
      Re: Control.Invoke and ref parameter

      Hi,

      Tried it, but I don't think it worked.
      [color=blue]
      > instead use:
      >
      > object[] args = { x, y };
      > oDataGridView.I nvoke(new MyHandler(MyFun c), args);[/color]

      This would have been equivalent to

      oDataGridView.I nvoke(new MyHandler(MyFun c), new object { x, y});

      Above, I believe, pass x and y by value, instead of by reference.





      --
      George


      "Barry Kelly" wrote:
      [color=blue]
      > George <wave@nospam.no spam> wrote:
      >[color=green]
      > > Does anyone know how Control.Invoke can invoke a method which has ref
      > > parameters?[/color]
      >[color=green]
      > > oDataGridView.I nvoke(new MyHandler(MyFun c), new object { ref x, ref y });[/color]
      >
      > instead use:
      >
      > object[] args = { x, y };
      > oDataGridView.I nvoke(new MyHandler(MyFun c), args);
      > // use args[0] (returned value of x)
      > // use args[1] (returned value of y)
      >
      > Now, args will have been modified based on what MyFunc did to x and y.
      >
      > -- Barry
      >
      > --
      > http://barrkel.blogspot.com/
      >[/color]

      Comment

      • Barry Kelly

        #4
        Re: Control.Invoke and ref parameter

        George <wave@nospam.no spam> wrote:
        [color=blue]
        > Tried it, but I don't think it worked.
        >[color=green]
        > > instead use:
        > >
        > > object[] args = { x, y };
        > > oDataGridView.I nvoke(new MyHandler(MyFun c), args);[/color]
        >
        > This would have been equivalent to
        >
        > oDataGridView.I nvoke(new MyHandler(MyFun c), new object { x, y});
        >
        > Above, I believe, pass x and y by value, instead of by reference.[/color]

        Did you even try the code? The arguments array passed in receives the
        changed values.

        To repeat myself, x and y don't change, the values in the *array*
        change. The code above *is* *not* *equivalent*, because you've thrown
        away the reference to the array.

        When I said "// use args[0]", I meant that it receives the new value of
        x.

        For example, try this code (in C# 2.0, but the principle is the same):

        ---8<---
        using System;
        using System.Windows. Forms;
        using System.Threadin g;

        class App
        {
        delegate void IntFiddler(ref int value);

        static void Main()
        {
        Form form = new Form();
        ThreadPool.Queu eUserWorkItem(d elegate
        {
        Thread.Sleep(10 00);

        // Run some code in the context of the UI.
        object[] args = { 21 };
        form.Invoke(new IntFiddler(Fidd le), args);
        Console.WriteLi ne(args[0]);
        });
        Application.Run (form);
        }

        static void Fiddle(ref int x)
        {
        x *= 2;
        }
        }
        --->8---

        -- Barry

        --

        Comment

        • Tom Spink

          #5
          Re: Control.Invoke and ref parameter

          George wrote:
          [color=blue]
          > Hi,
          >
          > Tried it, but I don't think it worked.
          >[color=green]
          >> instead use:
          >>
          >> object[] args = { x, y };
          >> oDataGridView.I nvoke(new MyHandler(MyFun c), args);[/color]
          >
          > This would have been equivalent to
          >
          > oDataGridView.I nvoke(new MyHandler(MyFun c), new object { x, y});
          >
          > Above, I believe, pass x and y by value, instead of by reference.
          >
          >
          >
          >
          >[/color]

          Hi George,
          [color=blue]
          > This would have been equivalent to[/color]

          I'm afraid it's not equivalent. Quite different in fact. In your code, you
          immediately instantiate an object array straight into the Invoke routine.
          In Barry's code, the array is instantiated *outside* of the routine. It's
          the instance of the array that changes, not the instance of the values
          inside the array.

          -- Tom Spink

          Comment

          • George

            #6
            Re: Control.Invoke and ref parameter

            Hi Barry.

            Thanks for your help again. It is my mistake that I checked against the
            wrong variables.

            In your first example, I checked against the value in x and y, instead of
            the new values in args.

            If you don't mind telling me: I spent a lot of time searching for an answer
            to this question before I posted here. I must have been searching the wrong
            topic. Do you know if Microsoft published a document regarding the proper
            use of

            Control.Invoke( Delegate, object[])

            especially when the Delegate contains "ref" or "out" parameters. It seems
            like

            1. without "ref" or "out", the object array *contents* are not modified.

            2. with "ref" or "out", the object array * contents" are modified.

            Is this a method marshalling thing?

            Thanks





            --
            George


            "Barry Kelly" wrote:
            [color=blue]
            > George <wave@nospam.no spam> wrote:
            >[color=green]
            > > Tried it, but I don't think it worked.
            > >[color=darkred]
            > > > instead use:
            > > >
            > > > object[] args = { x, y };
            > > > oDataGridView.I nvoke(new MyHandler(MyFun c), args);[/color]
            > >
            > > This would have been equivalent to
            > >
            > > oDataGridView.I nvoke(new MyHandler(MyFun c), new object { x, y});
            > >
            > > Above, I believe, pass x and y by value, instead of by reference.[/color]
            >
            > Did you even try the code? The arguments array passed in receives the
            > changed values.
            >
            > To repeat myself, x and y don't change, the values in the *array*
            > change. The code above *is* *not* *equivalent*, because you've thrown
            > away the reference to the array.
            >
            > When I said "// use args[0]", I meant that it receives the new value of
            > x.
            >
            > For example, try this code (in C# 2.0, but the principle is the same):
            >
            > ---8<---
            > using System;
            > using System.Windows. Forms;
            > using System.Threadin g;
            >
            > class App
            > {
            > delegate void IntFiddler(ref int value);
            >
            > static void Main()
            > {
            > Form form = new Form();
            > ThreadPool.Queu eUserWorkItem(d elegate
            > {
            > Thread.Sleep(10 00);
            >
            > // Run some code in the context of the UI.
            > object[] args = { 21 };
            > form.Invoke(new IntFiddler(Fidd le), args);
            > Console.WriteLi ne(args[0]);
            > });
            > Application.Run (form);
            > }
            >
            > static void Fiddle(ref int x)
            > {
            > x *= 2;
            > }
            > }
            > --->8---
            >
            > -- Barry
            >
            > --
            > http://barrkel.blogspot.com/
            >[/color]

            Comment

            • Barry Kelly

              #7
              Re: Control.Invoke and ref parameter

              George <wave@nospam.no spam> wrote:
              [color=blue]
              > If you don't mind telling me: I spent a lot of time searching for an answer
              > to this question before I posted here. I must have been searching the wrong
              > topic. Do you know if Microsoft published a document regarding the proper
              > use of
              >
              > Control.Invoke( Delegate, object[])[/color]

              I don't know. I originally (several years ago) just guessed that's what
              it would do when looking at MethodBase.Invo ke(), and ran a program to
              test out the theory. I was right :)
              [color=blue]
              > Is this a method marshalling thing?[/color]

              In so far as the CLR needs to take the arguments out of the array and
              put them on the stack and in regesters to call the method, and then copy
              out all the modified 'ref' and 'out' parameters back into the array,
              yes.

              -- Barry

              --

              Comment

              • Jeffrey Tan[MSFT]

                #8
                Re: Control.Invoke and ref parameter

                Hi George,

                In addition to Barry's reply, I still want to add some comment to your 2
                questions:

                Based on the C# language reference, "ref" is a method parameter keyword,
                which is only used in the parameter decoration.
                [color=blue]
                >1. without "ref" or "out", the object array *contents* are not modified.
                >2. with "ref" or "out", the object array * contents" are modified.[/color]

                The key point is where the keyword applies: does it apply to the object
                array itself or to the elements in the array?

                If you are marking the object array with "ref", it means that the array
                *contents* will remain the normal behavior, which we do not care, but the
                array itself may point to another array after invoking the method, please
                refer to the guide below:
                "Passing Arrays Using ref and out (C# Programming Guide) "


                If you are marking the elements in the array with "ref", it means the array
                remains the same, but the element itself may be *modified* after invoking.
                Your problem demonstrates this scenario.

                Actually, your scenario is somewhat specific, which I also can not find a
                definite sample or document regarding the syntax passing to
                Control.Invoke. (anyway, with the help of the community, you finally got the
                answer). In this scenario, I think we have to try with the existing C#
                document to find out the correct syntax.

                1. Based on "ref" document, "An argument passed to a ref parameter must
                first be initialized.", so we should initialize the object array outside of
                the method first.
                2. Marking "ref" in front of the object array element is invalid(because
                "ref" is only valid in method parameter), so we have no option of marking
                the "ref" keyword.

                With these 2 constraints, the code snippet Barry provided should be the
                only valid syntax.

                Hope this comment makes sense to you. If you have any concern, please feel
                free to tell me. Thanks.

                Best regards,
                Jeffrey Tan
                Microsoft Online Community Support
                =============== =============== =============== =====
                When responding to posts, please "Reply to Group" via your newsreader so
                that others may learn and benefit from your issue.
                =============== =============== =============== =====
                This posting is provided "AS IS" with no warranties, and confers no rights.

                Comment

                Working...