0

I made an APP that read the ADC value from a PIC using USB HID custom, the first test was to use a button to read the value and pass the read value to a progress bar and a textbox, that worked fine:

private void btnRead_Click(object sender, EventArgs e)
{
    txbCmd.Text = board.ADCVal().ToString();
    progressBar1.Value = Convert.ToInt32(txbCmd.Text);
}

If I start to click the button as fast as I can I'll get multiple read values from the ADC, like a continous read.

Then I try to put a timer with an event every 1.5 seconds to read the ADC (that is more slow than me pressing the button multiple times continously):

private void timer1_Tick(object sender, EventArgs e)
{
    txbCmd.Text = board.ADCVal().ToString();
    progressBar1.Value = Convert.ToInt32(txbCmd.Text);
}

When I start the timer, the first read is done without problems but the next read give error 5 that is access denied, if I let the program run one read is made and the next giveme error then the next is made and then again the next giveme error... I don't know why it work from a click button event and not from an timer event that use the same code.

EDIT

The ADCVal method has a call to another private method inside the same class named WriteUSB to send the read ADC command to the PIC board and then read the command reception confirmation from the board using the private method ReadUSB and finally wait for the read the ADC value from the PIC board, the error come from the WriteUSB call:

public UInt16 ADCVal()
{
    byte[] SndData = new byte[65]; 
    byte[] RcvData = new byte[65]; 

    SndData[0] = 0; //EP0 USB
    SndData[1] = _ADC_Val; //Cmd

    if (WriteUSB(ref SndData) == false) 
    {
        MessageBox.Show("Write USB Error: " + Marshal.GetLastWin32Error().ToString());
        return 0;
    }

    if (ReadUSB(ref RcvData, false) == true) 
    {
        if ((RcvData[1] == SndData[1]) && (RcvData[2] == 255))
        {

            if (ReadUSB(ref RcvData, false) == true)
            {
                return BitConverter.ToUInt16(RcvData, 2);
            }
            else
            {
                MessageBox.Show("Read USB Error: " + Marshal.GetLastWin32Error().ToString());
                return 0;
            }
        }
        else
        {
            MessageBox.Show("Read USB Error: " + Marshal.GetLastWin32Error().ToString());
            return 0;
        }
    }

    return 0;
}

And the private method WriteUSB has the WriteFile call (the ReadUSB has the ReadFile call code):

public bool WriteUSB(ref byte[] OutBuffer)
{
    int Bsize = OutBuffer.Length;
    string error;
    Int32 NumbersOfBytesWritten = 0;
    IntPtr UnManagedBuffer = Marshal.AllocHGlobal(Bsize); 
    Marshal.Copy(OutBuffer, 0, UnManagedBuffer, Bsize);

    if(WriteFile(USBDeviceInfo.WriteHandle, OutBuffer, Bsize, ref NumbersOfBytesWritten, IntPtr.Zero) == false)
    {
        error = Marshal.GetLastWin32Error().ToString();
        return false;
    }


    if (Marshal.GetLastWin32Error().ToString() == "0")
    {
        Marshal.FreeHGlobal(UnManagedBuffer);
        return true;
    }

    error = Marshal.GetLastWin32Error().ToString();
    return false;
}
Sodor
  • 55
  • 4
  • "Writefile called from ..." - there is no sample code that show that. Please consider inlining code so it is clear what code fails and with what errors. – Alexei Levenkov Jan 03 '15 at 04:22
  • @AlexeiLevenkov I forgot that, thanks I edited the question. the error that is giving me is the number 5 access denied – Sodor Jan 03 '15 at 04:59
  • `WriteFile` definition is still missing... Note that for [GetLAstWin32Error](http://msdn.microsoft.com/en-us/library/vstudio/system.runtime.interopservices.marshal.getlastwin32error(v=vs.100).aspx) to work correctly one need to have `DllImportAttribute(...SetLastError = true...)` in import. (I can't actually answer your question, but if you hope someone else will - remove all code unrelated to error - like random MessageBox calls and multiple calls to `GetLastWin32Error` and strange `ToString` calls everywhere). – Alexei Levenkov Jan 03 '15 at 06:09
  • Side note: reading `GetLastWin32Error` when no error happened during PInvoke makes absolutely no sense and will produce garbage results. This may be part of your problem. – Alexei Levenkov Jan 03 '15 at 06:14
  • Getting an "access denied" error from WriteFile() is exceedingly bizarre. It is however the error you'd get when you try to open a device more than once. – Hans Passant Jan 03 '15 at 10:15
  • @AlexeiLevenkov yes SetLastError is true in import, about the `GetLastWin32Error` calls I hadn't noticed that, in many places of the code I call it but there is no function that will give an error in first place, when actually the error in that cases are because a comparation of values, I feel ashamed (I will correct that)... on other hand I find a solution for the problem: I did that @JPAlioto recommended [HERE](http://stackoverflow.com/questions/1059696/c-sharp-can-a-timer-call-a-menu-event) is not the same error but it worked, can someone explain why it work? – Sodor Jan 06 '15 at 23:07
  • I'm not sure what you actually did in - "I did that " so I can't comment... Consider self-answering this question (even with "Solved by doing strange ...., followup question here") so it is clear the issue is closed and ask new question if you can show what you did and why you did not expect the change to fix the issue. – Alexei Levenkov Jan 06 '15 at 23:22

0 Answers0