[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1012
  • Last Modified:

C# - Invoke problem

Hello,

I have the following problem.
I get an attached exception on:
 this.Invoke(even, new object[] { buffer }); (line 17)

What do I do wrong?

Please help
Margarit

delegate void SetSlave(byte[] buffer);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            System.Threading.Thread.Sleep(500);
            byte[] buff = new byte[249];
            port.Read(buff, 0, 249); 
            SetSlavesData(buff); 
}
 
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void SetSlavesData(byte[] buffer)
        {
            if (this.InvokeRequired)
            {
                SetSlave even = new SetSlave(SetSlavesData);
                this.Invoke(even, new object[] { buffer });
            }
            else
            {
                int numOfSlaves, sentStrings;

Open in new window

1.JPG
0
margarit
Asked:
margarit
  • 7
  • 6
  • 2
1 Solution
 
abelCommented:
The error says that you use the wrong arguments. What is the declaration of the method you are invoking? It looks like you are only sending one argument, the buffer, and the error actually says that you need at least another argument: count.

Btw, you say "Invoke" but this is not a typical Invoke/Reflection question, correct? Can you show the body of Invoke?
0
 
margaritAuthor Commented:
Hello,
Thanks for the fast reply.
The declaration of method is: private void SetSlavesData(byte[] buffer)

Buffer is an array. Maybe here is a problem?
THANKS

private void SetSlavesData(byte[] buffer)
        {
            if (this.InvokeRequired)
            {
                SetSlave even = new SetSlave(SetSlavesData);
                this.Invoke(even, new object[] { buffer });
            }
            else
            {
                int numOfSlaves, sentStrings;
 
                numOfSlaves = buffer[1];     
                sentStrings = buffer[2];     
 
                this.slavesTable.Rows.Clear();
                this.slavesTable.Rows.Add(numOfSlaves);
          }
        }

Open in new window

0
 
abelCommented:
Do I understand this right, you are calling invoke using a delegate to call yourself recursively?

When you hover over the buffer, is it filled? I don't know why, but the error seems to come from somewhere else.

Normally, you do not need to do "new object[] { buffer}", not even with Invoke. I tried it to be sure, but when you use a byte array, it is fine if remove the array constructor:

this.Invoke(even, buffer);
but i'm afraid that all this is not really of any help to resolve your error.

Just as an example, i dug up a button_click event with a basic version of your code. It runs without errors:

delegate void TestArrayDelegate(byte[] b_array);
private void Q24344645_Click(object sender, EventArgs e)
{
    byte[] myArray = new byte[] {0,1,2};
    TestArrayDelegate myFunc= new TestArrayDelegate(DoTestArray);
    this.Invoke(myFunc, new object[] {myArray});
    // or: this.Invoke(myFunc, myArray);
}
 
private void DoTestArray(byte[] buffer)
{
    Debug.WriteLine(buffer[0]);
}

Open in new window

0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
CebikCommented:
hi :)
check this

public delegate void SetSlavesDataDelegate(byte[] buffer);
private void SetSlavesData(byte[] buffer)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new SetSlavesDataDelegate(SetSlavesData), buffer);
    }
    else
    {
        int numOfSlaves, sentStrings;
 
        numOfSlaves = buffer[1];     
        sentStrings = buffer[2];     
 
        this.slavesTable.Rows.Clear();
        this.slavesTable.Rows.Add(numOfSlaves);
  }
}

Open in new window

0
 
CebikCommented:
i sow now that you probably have delgate with other name so:
this will work..

public delegate void SetSlave(byte[] buffer);
private void SetSlavesData(byte[] buffer)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new SetSlave(SetSlavesData), buffer);
    }
    else
    {
        int numOfSlaves, sentStrings;
 
        numOfSlaves = buffer[1];     
        sentStrings = buffer[2];     
 
        this.slavesTable.Rows.Clear();
        this.slavesTable.Rows.Add(numOfSlaves);
  }
}

Open in new window

0
 
abelCommented:
@Cebik, what's the difference between my approach and your approach, or were you just following up on that? Btw, using "new object[]" or not doesn't break the code, strange as it may seem.
0
 
CebikCommented:
so what's wrong with her code?
i writed the same code like her...
but in my code i'm not using "new object[]" and it's working! (checked!)
that's why i writed it..
0
 
CebikCommented:
ok.. i've found the same using in your code now..
so the differents is that i corrected her code not making new correct code

i didn't want to take your points :)
0
 
CebikCommented:
and.. she is doing this because she is changing properties on a form from different thread..
maybe the problem is that you are getting element index 1 and 2 not 0 and 1..
here is example app based on your..
make new windows application and paste the code..

good luck margarit! :)

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        DataGridView slavesTable = new DataGridView();
 
        public Form1()
        {
            InitializeComponent();
 
            slavesTable.Dock = DockStyle.Fill;
            slavesTable.Columns.Add("0", "0");
            slavesTable.Columns.Add("1", "1");
            slavesTable.Columns.Add("2", "2");
            this.Controls.Add(slavesTable);
        }
 
        public delegate void SetSlave(byte[] buffer);
        private void SetSlavesData(byte[] buffer)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new SetSlave(SetSlavesData), buffer);
            }
            else
            {
                int numOfSlaves, sentStrings;
 
                //numOfSlaves = buffer[0];  //indexing starting from 0 to elements count -1 !!
                numOfSlaves = buffer[1];
                sentStrings = buffer[2];
 
                //this.slavesTable.Rows.Clear();
                //this.slavesTable.Rows.Add(numOfSlaves);
                this.slavesTable.Rows.Add(buffer[0], buffer[1], buffer[2]);
            }
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            Thread nt = new Thread(new ThreadStart(Thread1));
            nt.Start();
        }
 
        private void Thread1()
        {
            Random rnd = new Random();
            while(true)
            {
                Thread.Sleep(1000);
                byte[] buffer = new byte[] { Convert.ToByte(rnd.Next(0, 255)), Convert.ToByte(rnd.Next(0, 255)), Convert.ToByte(rnd.Next(0, 255)) };
                SetSlavesData(buffer);
            }
        }
    }
}

Open in new window

0
 
abelCommented:
No problem, it just looked a bit strange. Sorry for fuzzing about it...

Btw, as you noticed, this is apparently about cross-thread calls. I am wondering about the error, though. It mentions a parameter "count" which isn't there and is apparently wrong. I don't see that parameter on the place of the error. Is the error really occurring on that point, or at a deeper level, which is somehow hidden for the debugger?
0
 
CebikCommented:
that's right..
it must be somwhere else..
she must give us stack trace..
i've checked this.. and both of this is working..


this.Invoke(myFunc, new object[] {myArray});
this.Invoke(myFunc, myArray);

Open in new window

0
 
abelCommented:
(if you don't want to know the whole story behind it, or how to keep this from happening in the future, just read the bold lines below)
The error
I think, Cebik, that you are on the right page there. The buffer is, of course, indexed from zero. But the error received is not about IndexOutOfRangeException (see screenshot 1), but about an ArgumentOutOfRangeException. I was puzzled by that, because there seemed to be no call where that actually happened.

The count param
Until my eye was caught by the Rows.Add(count) method. That was where the "count" parameter was! Assuming that slavesTable was a DataGridView I tried to mimic the situation again and this time I succeeded.

Not the right line
My last comment, about the error taking place somewhere else, was apparently correct. See the second screenshot. The Visual Studio Debugger is not capable of diving into the queued method (see http://weblogs.asp.net/justin_rogers/pages/126345.aspx for what happens under the hood) and shows the line where the Invoke takes place.

How to debug
So, how could you actually debug this correctly? Quite simply: put a breakpoint at the beginning of the method (just after the "else") that is being invoked and you can step through it with F10.

How to solve
How to solve it? Possibly by following up on Cebik's advice: maybe you have the wrong index. Or maybe you didn't want to use the data in the buffer at all as count for adding rows (as Cebik suggests) and you just want to add the contents of the buffer.

The code that Cebik shows you will add three cells in one new row.

The code that you had originally, will add buffer[1] amount of rows. Because buffer[1] was holding zero or a negative value, you got the error you saw.

Now you know what is actually going on, you know how to solve it, to debug it and how to display it.

-- Abel --

ScreenShot232.png
ScreenShot231.png
0
 
abelCommented:
Note1: the screenshot232 above shows the yellow line on Invoke, but the error is on Debug.WriteLine(buffer[4]), which is out of bounds there are 3 elements, so buffer[2] would have been the last)

Note2: the screenshot231 above shows the yellow line on Invoke, but the error is on dataGridView1.Rows.Add(0), which is not allowed.

Note3: placing a breakpoint at the opening bracket of DoTestArray in the code above actually made it possible to use F10 to step through, but once the error was raised, it would jump back to this.Invoke.
0
 
CebikCommented:
i was thinking about this rows.add also but i was almoust sleep yesterday..
glories for you ;)
0
 
margaritAuthor Commented:
THANKS A LOT
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 7
  • 6
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now