Avatar billede microjet Nybegynder
25. november 2008 - 13:49 Der er 20 kommentarer og
1 løsning

Summary "hint" i ClassLibrary - virker ikke!

Hvis man benytter nedenstående metode vil der fremkomme hints med den beskrivelse der er i summary for hver variabel, når man holder musen over en af variablerne... og det er jo ret genialt

Det virker bare ikke når jeg skal bruge metoden i ClassLibrary'et... inden for selve ClassLibraryet fremkommer de små hints!

Altså holder man musen over variablen "hoejde" fremkommer hint'et:
"Højden af kassen i cm"

Er det bare sådan eller er det muligt at se disse hints/descriptions når man benytter sine DLL'er

Jeg håber der er nogel der forstår hvad jeg mener :-)


      #region Manager Constructors
        /// <summary>
        /// Beregner rumfanget af en kasse
        /// </summary>
        /// <param name="hoejde">Højden af kassen i cm</param>
        /// <param name="laengde">Længden af kassen i cm</param>
        /// <param name="bredde">Bredden af kassen i cm</param>
        public Rumfang(Int hoejde, int laengde, int bredde)
        {

          int rumfang = hoejde*laengde*bredde
          bla...
          bla...

        }
Avatar billede jokkejensen Novice
25. november 2008 - 13:54 #1
Hvad hvis du har 2 projecter åben i samme solution ?

/J
Avatar billede aaberg Nybegynder
25. november 2008 - 15:11 #2
Først skal du gå ind på det projekt som du har lavet kommentarer til. Højreklik på projektet i Visual Studio, og tryk "Properties". Vælg "Build" tabben, og mærk af boksen "Xml documentation file". Næste gang du builder dit projekt, vil der blive genereret en XML fil som ligger ved siden af dll/exe filen. Når du kopiere dll/exe filen, så sørg for at kopiere denne xml fil med. Så længe XML filen ligger ved siden af dll/exe filen, vil du se kommentarene i Visual Studio.
Avatar billede microjet Nybegynder
02. december 2008 - 10:55 #3
Endnu engang et præcist svar fra aaberg ;-)

Det virkede med det samme, så tak for det... du kan blot poste et svar!

Nu mens jeg har fat i dig,så kunne du måske hjælpe mig med et andet lille problem. Jeg har en datapakke hvor der er 4 returværdier. "ReturnValue1..4" string, int, float og bool samt en ennum "ReturnType" ( enum ReturnType{string=1,int, float, bool} )

Når pakken sendes afsted er ReturnType valgt...eks "int". så vil svaret blive konverteret til en int, men også til float og string, da det jo også er muligt.

Så når pakken kommer retur har man f.eks svaret både som int og string, men da man har valgt en returntype, skal det på en eller anden måde gøres enkelt at få det svar retur somman på forhånd har valgt at få, men man skal jo også kunne få fat i de andre typer.

Når der nu er 4 typer havde jeg tænkt noget lignende dette:

ReturnValue[ReturnType] ...altså lidt array of record agtigt, men ved ikke rigtig hvordan det skal laves i C#

Har du et godt forslag!
Avatar billede aaberg Nybegynder
02. december 2008 - 11:19 #4
Hej microjet,

Hvorfor ikke bare lade returtypen være object, og nøjes med at returnere 1 værdi? Du kan jo altid caste og konvertere mellem typerne.

object theReturnVal = GetValue();

skal du tjekke om theReturnVal er en int, skriver du:
if (theReturnVal.GetType() == typeof(int))
  ...

skal du bruge en string:
string theReturnValAsString = theReturnVal.ToString();

Ved du at det er en integer, og skal bruge den i en int variabel, skriver du:
int theReturnValAsInt = (int)theReturnVal;


Eller har jeg helt misforstået problemstillingen?
Avatar billede microjet Nybegynder
02. december 2008 - 12:19 #5
Hej aaberg

Det er korrekt forstået, det er en datapakke der bliver sendt frem og tilbage mellem nogle dll'er via delegates. Det mest enkle er måske bare at resultatet returneres i den type man har valgt fra start... så må man selv konverterer til andre typer. Du kan herunder se den klasse som datapakken består af

Jeg har tænkt på at lave ReturnAnswer af typen object, men det har givet mig nogle nye problemer med invoke i applikatiionen. pt. virker det hvis ReturnAnswer er af typen string

    public class HBDataPacket
    {
        //Interface selection
        public _Interface Interface = _Interface.None;
        //COMport settings
        public string COMStartStr;
        public string COMEndStr;
        public string COMTxStr;
        public string COMname;
        public int  COMBaudrate;
        public bool COMIncludeStartStr;
        public bool COMIncludeEndStr;
        public int  COMpacketsize;
        //CAN settings
        public string CANopen;

        //Profi settings
        public string ProfiBus;

        //MODbus settings
        public string Modbus;
        //Common settings
        public int PacketID;
        public int Max;
        public int Min;
        public string Unit;

        public bool Read;
        public bool Write;
        public int ReTransmit;
        public int Timeout;
        public bool Error;
        public string ErrorMgs;
        public int TxTimeStamp;
        public int State;

        public enum ReturnType {String=1, Integer, Floatingpoint, Boolean};

        public string ReturnAnswer1;
        public int    ReturnAnswer2;
        public float  ReturnAnswer3;
        public bool  ReturnAnswer4;
    }
Avatar billede microjet Nybegynder
02. december 2008 - 12:40 #6
Hmmm jeg tror faktisk jeg har fået det til at virke med ReturnAnswer som object.. jeg skal lige arbejde lidt mere med det før jeg er helt sikker på at det er den bedste løsning... så tusind tak!
Avatar billede aaberg Nybegynder
02. december 2008 - 13:27 #7
Et forslag på en måde at gøre det på:

public class HBDataPacket
{
  ..
  ..
  ..

  public object ReturnAnswer;

  public int GetReturnAnswerAsInt()
  {
      return Convert.ToInt32(ReturnAnswer);
  }

  public string GetReturnAnswerAsString()
  {
      return ReturnAnswer.ToString();
  }

  public float GetReturnAnswerAsFloat()
  {
      return Convert.ToSingle(ReturnAnswer);
  }

  osv..
}
Avatar billede microjet Nybegynder
03. december 2008 - 11:52 #8
Hej aaberg

Jep det virker fint nu!:-D

Jeg har lige ét spørgsmål mere vedr. at afmelde delegates.

"abonnement" på delegate i Form Load

        private void Form1_Load_1(object sender, EventArgs e)
        {

            Device1.NewDeviceData += new HBDevice.DeviceDataDelegate(DataRecieved);

        } 


Afslutter abonnement i formClosing


      private void Form1_FormClosing(object sender, FormClosingEventArgs e)
      {       
          Device1.NewDeviceData -= new HBDevice.DeviceDataDelegate(DataRecieved);

      }


Det der bare sker, er at abonnementet ligesom ikke bliver afsluttet før formen bliver lukket ned hvilket giver en exception. Hvis der konstant kommer data fra comporten ind i min applikation, opstår fejlen, for så bliver der jo konstant udvekslet data mellem mine delegates.

Hvordan kan man sikre sig at disse delegate er færdigafviklet inden formen lukker?

Hvis jeg stopper abonnementet selv inden jeg luker formen ned virker det perfekt!


Her er fejlbeskrivelsen:


System.ObjectDisposedException was unhandled
  Message="Der er ikke adgang til et fjernet objekt.\r\nObjektnavn: 'Form1'."
  Source="System.Windows.Forms"
  ObjectName="Form1"
  StackTrace:
      ved System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
      ved System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
      ved WindowsFormsApplication1.Form1.test(HBDataPacket datapacket) i C:\C#\DelegateTest\Application\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:linje 86
      ved DeviceClassLibrary.HBDevice.OnDeviceData(HBDataPacket datapacket) i C:\C#\DelegateTest\DeviceClassLibrary\DeviceClassLibrary\DeviceClass.cs:linje 153
      ved DeviceClassLibrary.HBDevice.DeviceDataRecieved(HBDataPacket datapacket) i C:\C#\DelegateTest\DeviceClassLibrary\DeviceClassLibrary\DeviceClass.cs:linje 160
      ved MultiplexClassLibrary.HBMultiplex.OnMultiplexData(HBDataPacket datapacket) i C:\C#\DelegateTest\MultiplaxClassLibrary\MultiplexClassLibrary\MultiplexClass.cs:linje 21
      ved MultiplexClassLibrary.HBMultiplex.MultiplexDataRecieved(HBDataPacket datapacket) i C:\C#\DelegateTest\MultiplaxClassLibrary\MultiplexClassLibrary\MultiplexClass.cs:linje 27
      ved ComPortClassLibrary.HBComPort.OnComportData(HBDataPacket datapacket) i C:\C#\DelegateTest\ComPortClassLibrary\ComPortClassLibrary\ComportClass.cs:linje 341
      ved ComPortClassLibrary.HBComPort.ComportDataRecieved(Object sender, SerialDataReceivedEventArgs e) i C:\C#\DelegateTest\ComPortClassLibrary\ComPortClassLibrary\ComportClass.cs:linje 326
      ved System.IO.Ports.SerialPort.CatchReceivedEvents(Object src, SerialDataReceivedEventArgs e)
      ved System.IO.Ports.SerialStream.EventLoopRunner.CallReceiveEvents(Object state)
      ved System.Threading._ThreadPoolWaitCallback.WaitCallback_Context(Object state)
      ved System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
      ved System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal(_ThreadPoolWaitCallback tpWaitCallBack)
      ved System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(Object state)
  InnerException:
Avatar billede microjet Nybegynder
03. december 2008 - 11:58 #9
Jeg tænkte at dette måske kunne have en betydning
Jeg er ikke helt med påhvordan dette her "invoke" fungerer, men jeg har denne fungerende stump kode, som jeg tænkte på måske kunen være årsagen!

                if (this.richTextBox1.InvokeRequired)
                {
                    testdelegate d = new testdelegate(test);
                    this.Invoke(d, new object[] { datapacket });
                }
Avatar billede aaberg Nybegynder
03. december 2008 - 12:41 #10
Jeg tror det er din invoke som er problemet. Jeg går ud fra at du har noget kørende i en anden tråd, siden du bruger invoke?

I stedet for at bruge Thread eller ThreadPool, bør du bruge en BackgroundWorker for at starte en ny tråd. BackgroundWorker er beregnet til at skulle bruges sammen med en form. Da undgår du at skulle bruge invoke, og du undgår at der kommer en Exception når du lukker formen. Grunden til at du får denne Exception er, at selvom din form lukkes, køre tråden videre. På et eller andet tidspunkt prøver tråden at køre Invoke på formen, men formen er Disposed, og du får altså en Exception.
Avatar billede microjet Nybegynder
03. december 2008 - 12:56 #11
Jeg bruger kun delegates, men det er vel også en slags thread's. Hvis jeg manuelt aftryder tråden/abonnementet ved at eksekvere:

Device1.NewDeviceData -= new HBDevice.DeviceDataDelegate(DataRecieved);

inden jeg lukker formen får jeg ingen excption, men gør jeg det OnFormClosing, kommer den

Koden med invoke burde slet ikke kunne eksekveres da abonnementet jo er afsluttet. Jeg tror måske der sker det at jeg stopper abonnementet mens der stadig eksekveres kode i den metode som der blev sendt data til via delegates.

Når jeg så lukker formen er metoden stadig aktiv og kan så ikke få adgang til formen

Lyder det helt hen i vejret??
Avatar billede aaberg Nybegynder
03. december 2008 - 13:25 #12
Delegates køre i samme tråd som de bliver eksekveret fra. Hvis din Device klasse opretter en ny tråd og eksekverer delegatene derfra, har du flere tråde, ellers ikke.

Ifølge den stacktrace du har copy-pasted ind, ser det ud som om at fejlen sker i en metode som hedder test(HBDataPacket datapacket) på linje 86. Kan jeg se lidt mere af din kode?
Avatar billede microjet Nybegynder
03. december 2008 - 13:47 #13
Det er korekt, men hvis nu metoden test er blevet kaldet via en delegate og denne tråd afbrydes mens metoden test stadig eksekverer kode, så er det klart at metoden test ikke kan få fat i form1 som jo er ved at lukke ned, så hvordan sikre man sig at alle tråde er færdig afviklet inden formen afsluttes


Abonnement på delegate i DLL:
Device1.NewDeviceData += new HBDevice.DeviceDataDelegate(DataRecieved);


Sådan starter og stopper jeg abonnement:
NewData += new testdelegate(DataRecieved);
NewData -= new testdelegate(DataRecieved);


Kode:

        public delegate void testdelegate(HBDataPacket datapacket);
        public event testdelegate NewData;


        public void DataRecieved(HBDataPacket datapacket)
        {
            OnData(datapacket);
        }     
       
       
        private void OnData(HBDataPacket datapacket)
        {
            if (NewData != null)
                test(datapacket);
        }


        public void test(HBDataPacket datapacket)
        {

                if (this.richTextBox1.InvokeRequired)
                {
                    testdelegate d = new testdelegate(test);
                    this.Invoke(d, new object[] { datapacket });
                }

                else
                {
                    this.label6.Text = datapacket.GetReturnAnswerAsString();
                    //udskriver resultat til label
                    this.richTextBox1.AppendText(datapacket.GetReturnAnswerAsStrin());
                  //udskriver resultat til richtextbox
                }

        }
Avatar billede microjet Nybegynder
03. december 2008 - 14:14 #14
Det kan godt være det er en keglet måde at gøre det på, men deter deneneste måde jeg har fået det til at virke tilfredsstillende på, men i applikationen gør det ingen forskel om jeg har en event på delegate eller ej. Jeg havde først lavet det helt uden event... altså:

Device1.NewDeviceData += new HBDevice.DeviceDataDelegate(test);

Men det giver samme fejl

Kan det have noget med EndInvoke at gøre, for det her jeg ingen steder i min kode?
Avatar billede aaberg Nybegynder
03. december 2008 - 14:41 #15
EndInvoke skal kun bruges sammen med BeginInvoke, som er en asynkron invoke. Det er ikke det der er problemet. Det ser ud til at HBDevice klassen køre i en anden tråd. Hvis alt kørte i din hovedtråd, ville dette problem ikke opstå.

Prøv:

public delegate void testdelegate(HBDataPacket datapacket);
public event testdelegate NewData;

private bool isReceivingPackage = false;


public void DataRecieved(HBDataPacket datapacket)
{
  OnData(datapacket);
}   
     
     
private void OnData(HBDataPacket datapacket)
{
  if (NewData != null)
      test(datapacket);
}


public void test(HBDataPacket datapacket)
{
  this.isReceivingData = true;
  if (this.richTextBox1.InvokeRequired)
  {
      testdelegate d = new testdelegate(test);
      this.Invoke(d, new object[] { datapacket });
  }

  else
  {
      this.label6.Text = datapacket.GetReturnAnswerAsString();
      //udskriver resultat til label
      this.richTextBox1.AppendText(datapacket.GetReturnAnswerAsStrin());
      //udskriver resultat til richtextbox
  }
  this.isReceivingData = false;
}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{     
  Device1.NewDeviceData -= new HBDevice.DeviceDataDelegate(DataRecieved);

  while(!this.isReceivingData)
      Thread.Sleep(100);
}
Avatar billede microjet Nybegynder
03. december 2008 - 15:01 #16
Jep det var også min første indskydelse, så det har jeg allerede prøvet men det virkede desværre ikke :-(
Avatar billede microjet Nybegynder
03. december 2008 - 15:04 #17
Jeg prøvede da lige éen gang til med lige præcis dit forslag, men det hjælper ikke
Avatar billede microjet Nybegynder
03. december 2008 - 15:18 #18
Fejlen opstår så snart Form1 er lukket ned, så brokker den sig over at der ikke mere er forbindelse til objektet "Form1". Så man skal på en eller anden måde ha fjernet tilhørsforholdet inden man lukker formen ned. 

Jeg har testet med breakpoints at det ikke er er en ny pakke der kommer


              this.isReceivingData = true;
                if (this.richTextBox1.InvokeRequired)
                {
                    testdelegate d = new testdelegate(test);
fejler her-->      this.Invoke(d, new object[] { datapacket });
                }
Avatar billede aaberg Nybegynder
03. december 2008 - 15:20 #19
Jeg ser jeg lavede en fejl i det jeg skrev. Prøv at skifte følgende ud

while(!this.isReceivingData)
      Thread.Sleep(100);

med dette

while(this.isReceivingData)
      Thread.Sleep(100);
Avatar billede microjet Nybegynder
03. december 2008 - 15:36 #20
Den går i uendeligt loop, da isReceivingData aldrig bliver false


Jeg kan da løse det på nedenstående måde, men det er jo ikke en særlig pæn måde at gøre de på.... men det virker ;-)


              if (this.richTextBox1.InvokeRequired)
                {
                    try
                    {
                        testdelegate d = new testdelegate(test);
                        this.Invoke(d, new object[] { datapacket });
                    }
                    catch (Exception)
                    {
                    }
                }
Avatar billede aaberg Nybegynder
03. december 2008 - 20:56 #21
:-), jaja, virker det så virker det. Jeg tror næsten jeg ville blive nød til at sidde og rode lidt med det, hvis jeg skulle finde en mere elegant løsning. Men, din løsning virker, det er det vigtigste.  :-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester