1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

Does anyone here know a little C#

Discussion in 'Computers and Networks' started by Ian Rogers, Mar 3, 2014.

  1. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,170
    Likes:
    910
    Location:
    Rochdale UK
    I'm finally ditching VB6 as my PC interface RAD tool as I can't really get it to work on the new Windows platforms..

    Now I can handle C# but I have a little trouble understanding "Delegates"... I know these are needed to interact between classes.... I also know that in C++ we used DDX to exchange data between modules..

    I have run through every tutorial... I get things working BUT!!! I need a good understanding...

    Senario:----

    I have a text string arriving on the COM port.... "Hello world!".
    I want to place this in the textbox on my form...

    In VB6 I did this..

    TextBox1.Text = MsComm1.Input

    In C# ( and newer basics ) I receive a permissions error...

    I need to set up a delegate ( friend function) to allow me access to the textbox outside its scope!!!

    Can anyone explain ( in English ) the functionality of a delegate??? I need to understand this so I don't need to scour the internet for example code...
     
  2. atferrari

    atferrari Well-Known Member

    Joined:
    Oct 8, 2003
    Messages:
    2,812
    Likes:
    121
    Location:
    Buenos Aires - Argentina
    Hola Ian,

    Could you reproduce the permission error here?
     
  3. dougy83

    dougy83 Well-Known Member

    Joined:
    May 18, 2008
    Messages:
    2,672
    Likes:
    215
    Location:
    Brisbane, Australia
    They're basically just function pointers. Read http://msdn.microsoft.com/en-us/library/ms173171.aspx

    Is the "permissions error" actually a cross-thread access of UI component warning? This happens when you try to access one of the UI components on the form from a thread other than the main UI thread. A delegate may be used in this case to re-call the function in the UI thread... I can't tell from what you wrote.
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,170
    Likes:
    910
    Location:
    Rochdale UK

    Yep!! Its all the cross threading I don't get..... When I program in C++ I can access any component on a form.. I can't get my head around this aspect....

    I really don't understand why Microsoft just assumes no-one does "lone" development any more... If I develop an application, I hate the idea that components that I make, I then cannot access...

    Everything I read about this subject, doesn't cover the basic why's and wherefor's They give the typical ( never used) example and expect it to what we need!!

    I will write a section of code and post it tonight!!
     
  6. dougy83

    dougy83 Well-Known Member

    Joined:
    May 18, 2008
    Messages:
    2,672
    Likes:
    215
    Location:
    Brisbane, Australia
    Well there's the main UI thread that runs the controls' events, and there's potentially other threads for certain asynchronous events, e.g. receiving data from a serial port (perhaps) or some event from a background task that's running.

    Anyway, to set text in a textbox you simply invoke a function from within the main UI thread. You can use the following pattern to check if the invoke is required, and just call the same function again in the appropriate thread. The component you check against can be any component on the form (I assume).
    Code (text):

    private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
            {
                if (textBox1.InvokeRequired)
                {
                    textBox1.BeginInvoke(new Action<object, System.IO.Ports.SerialDataReceivedEventArgs>(serialPort1_DataReceived), sender, e);
                }
                else
                {
                    byte []buff = new byte[serialPort1.BytesToRead];
                    serialPort1.Read(buff, 0, buff.Length);
                    textBox1.Text = "New Data: " + BitConverter.ToString(buff);
                }
            }
    EDIT: note: The generic Action<> class allows you to create delegates without having to explicitly declare/define them.
     
    Last edited: Mar 3, 2014
  7. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,170
    Likes:
    910
    Location:
    Rochdale UK
    atferrari Sorry Hi!

    dougy83 .. Thanks... I haven't seen that " Action<> " before... I'll read up on it... It basically looks like all I need is this simple delegate to get to where I want to be.... I take it, its the same in VB2012?
     
  8. dougy83

    dougy83 Well-Known Member

    Joined:
    May 18, 2008
    Messages:
    2,672
    Likes:
    215
    Location:
    Brisbane, Australia
    Action<> is handy, but not essential. Action is available in VB, but obviously the syntax is different; instead of Action<class1, class2>(func) you'll use Action(Of class1, Of class2)(func), I believe.
     
    Last edited: Mar 3, 2014
  9. NorthGuy

    NorthGuy Well-Known Member

    Joined:
    Sep 8, 2013
    Messages:
    1,218
    Likes:
    206
    Location:
    Northern Canada
    I believe Microsoft has free VC++ for download, so if you don't like C# you can always use C/C++.
     
  10. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,170
    Likes:
    910
    Location:
    Rochdale UK
    I do use C++.. But I used to like VB6 for RAD applications... C++ is too finiky for small test programs.. I feel that C# is a bit finiky too...

    Lets say I'm simulating a GPS receiver... I can produce the output of a GPS unit in VB6 and cram it into Proteus..

    I don't want to write a full blown application every time I need to simulate a component... VB6 was excellent for that purpose.. Trying to achieve the same agility from C++ was tedious... Baa Humbug!!
     
  11. NorthGuy

    NorthGuy Well-Known Member

    Joined:
    Sep 8, 2013
    Messages:
    1,218
    Likes:
    206
    Location:
    Northern Canada
    For test programs, I often use Console applications. It takes only few minutes to create one, you can interact with it, you can caputre the output if you want. You can even integrate it with your IDE. Say, in MPLAB it can output into the Output window.
     
  12. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,170
    Likes:
    910
    Location:
    Rochdale UK
    I think you would need to see one of my applications for testing my systems. We are just finishing one of the better simulators. The complete crane has been modeled in Blender. I need to interface 3ds modles in VB6 to interact directly... I like the idea of a console app but for the purpose of simulating a crane, forklift or excavator, a graphical representation is much easier to work with..... At work I still use XP so it's not an issue, but at home I only have Windows 7 and 8
     
  13. dougy83

    dougy83 Well-Known Member

    Joined:
    May 18, 2008
    Messages:
    2,672
    Likes:
    215
    Location:
    Brisbane, Australia
    You can write console applications in C# too.

    I'm not sure where VB6 is ever better than VB.NET or C#.
     
  14. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,170
    Likes:
    910
    Location:
    Rochdale UK
    Just simplicity!! Its not really an OOP development platform... I know its dated so that's why I've re-taken up C# I used to play with .net some years back with the tinyCLR embedded systems.... I just need to get back into it!!
     
  15. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,170
    Likes:
    910
    Location:
    Rochdale UK
    Ok!! I have been doing some research
    I came across this piece of code..... At first it seemed nonsense, after debugging I see what the delegate (function pointer ) is doing....
    Code (c):

    using System;
    using System.IO;

    namespace BoilerEventAppl
    {

        // boiler class
        class Boiler
        {
            private int temp;
            private int pressure;
            public Boiler(int t, int p)
            {
                temp = t;
                pressure = p;
            }

            public int getTemp()
            {
                return temp;
            }
            public int getPressure()
            {
                return pressure;
            }
        }
        // event publisher
        class DelegateBoilerEvent
        {
            public delegate void BoilerLogHandler(string status);

            //Defining event based on the above delegate
            public event BoilerLogHandler BoilerEventLog;

            public void LogProcess()
            {
                string remarks = "O. K";
                Boiler b = new Boiler(100, 12);
                int t = b.getTemp();
                int p = b.getPressure();
                if (t > 150 || t < 80 || p < 12 || p > 15)
                {
                    remarks = "Need Maintenance";
                }
                OnBoilerEventLog("Logging Info:\n");
                OnBoilerEventLog("Temperature " + t + "\nPressure: " + p);
                OnBoilerEventLog("\nMessage: " + remarks);
            }

            protected void OnBoilerEventLog(string message)
            {
                if (BoilerEventLog != null)
                {
                    BoilerEventLog(message);
                }
            }
        }
        // this class keeps a provision for writing into the log file
        class BoilerInfoLogger
        {
            FileStream fs;
            StreamWriter sw;
            public BoilerInfoLogger(string filename)
            {
                fs = new FileStream(filename, FileMode.Append, FileAccess.Write);
                sw = new StreamWriter(fs);
            }
            public void Logger(string info)
            {
                sw.WriteLine(info);
            }
            public void Close()
            {
                sw.Close();
                fs.Close();
            }
        }
        // The event subscriber
        public class RecordBoilerInfo
        {
            static void Logger(string info)
            {
                Console.WriteLine(info);
            }//end of Logger

            static void Main(string[] args)
            {
                BoilerInfoLogger filelog = new BoilerInfoLogger("d:\\boiler.txt");
                DelegateBoilerEvent boilerEvent = new DelegateBoilerEvent();
                boilerEvent.BoilerEventLog += new DelegateBoilerEvent.BoilerLogHandler(Logger);
                boilerEvent.BoilerEventLog += new DelegateBoilerEvent.BoilerLogHandler(filelog.Logger);
                boilerEvent.LogProcess();
                Console.ReadLine();
                filelog.Close();
            }//end of main

        }//end of RecordBoilerInfo
    }
     
    Correct me if I'm wrong....
    We created a instance of BoilerInfoLogger called filelog..
    We created a instance of DelegateBoilerEvent
    We then created two function pointers.. One to filelog.logger and one to this.logger.

    We now have cascaded two events when BoilerEventLog is called.. The first event contains a pointer to the Logger function in RecordBoilerInfo and the second pointer to the logger function in BoilerInfoLogger.

    I had to debug it several times to see what's happening... The way I had it in my mind was totally opposite of what's happening...

    I'm going to try a few problems of my own to see if it has really sunk in!!
     
  16. dougy83

    dougy83 Well-Known Member

    Joined:
    May 18, 2008
    Messages:
    2,672
    Likes:
    215
    Location:
    Brisbane, Australia
    Yes, what you said is right. Normally, registering events doesn't require creation of a new delegate:
    Code (text):
                boilerEvent.BoilerEventLog+= Logger;
                boilerEvent.BoilerEventLog+= filelog.Logger;
    is sufficient.
     
  17. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,170
    Likes:
    910
    Location:
    Rochdale UK
    Ok!! Back on C# again....... I have to make a small HID C# program... I have tried this

    https://github.com/MightyDevices/MightyHID.

    I first used the DLL, but the reference was in error..... It was written for NET4 and I'm running 3.5.. So I downloaded the source for the DLL and it compiles fne ( The only reference I had to get rid of was "System.Theading.task" doesn't affect compilation so I seem ok!

    When I use MighyHID.DLL the reference now works.... My issue... In the main program they create a "FileStream" instance with a buffer of 32 bytes.... Now my HID device has 64 so I edited any code to a 64 byte buffer..

    When run FileStream.Write()... FileStream.Flush() and FileStream.Read().. All whinge of "Incorrect Parameters"

    But checking through the code the parameters are great.... I have upped the buffer to 256 ( in case ) but the error is still there.... Any idea's

    If you need screenshots I'll give them..... I could try using 2013 ( which I have at work) with the original DLL..
     
  18. dougy83

    dougy83 Well-Known Member

    Joined:
    May 18, 2008
    Messages:
    2,672
    Likes:
    215
    Location:
    Brisbane, Australia
    Yes. Include the code around where the error is occurring and the actual error message while you're at it. I've never used MightyHID, but if you give some information, I might be able to help.
     
  19. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,170
    Likes:
    910
    Location:
    Rochdale UK
    I'll do it when I get home... I have more time then... its 12:17 here in the uk, so about 6 hours and I should be done..

    Cheers for looking anyway!!
     
  20. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,170
    Likes:
    910
    Location:
    Rochdale UK
    Ok! Here is the fault occurring when _FileSteam(data,0,data.length);

    C# 2.jpg
    Then if I decrease data.length by 1 it must work, but then wont' flush..
    C# 1.jpg

    If I rem out the flush then the program continues, but the read fails with _FileSteam.read(data).

    Here is the Exception in detail..
    C# 3.jpg

    If you want the full code I can post it.... Remember that I had to remove "System.Threading.Tasks." as it was a bad reference.... When looking at the exception... It gets into threading before it fails....
     
  21. NorthGuy

    NorthGuy Well-Known Member

    Joined:
    Sep 8, 2013
    Messages:
    1,218
    Likes:
    206
    Location:
    Northern Canada
    HID requires buffer length to be exactly the "size of the input report + 1". The first byte in the buffer must be set to 0 prior to calling. Otherwise it won't work. The file read will copy the report into the buffer starting from the second byte.

    I'm not sure C# call will convey all the parameters to the underlying "ReadFile" call exactly as you specify them. If not, you will need to call "ReadFile" directly.
     

Share This Page