Avatar billede Red0z Nybegynder
22. september 2009 - 12:53 Der er 25 kommentarer og
1 løsning

Data Overloading

Hey guys! Har fået sat mit program op, og det kan køre med en lille mængde filer svarende til 2 CD'ere.

Men hvis jeg kører det med dét der svarer til 29,9GB så crasher programmet næsten med det samme, er helt uvis på hvilken fejl jeg har lavet. :) Men den fejlmeddelse jeg får er :

The CLR has been unable to transition from COM context 0xd40ee0 to COM context 0xd41130 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this problem, all single threaded apartment (STA) threads should use pumping wait primitives (such as CoWaitForMultipleHandles) and routinely pump messages during long running operations.



Jeg er som sagt helt blank på hvad.
Her er koden som loader de enkelte filer.

        protected string MD5HashFromFile(string fileName)
        {
            FileStream file = new FileStream(fileName, FileMode.Open);
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] retVal = md5.ComputeHash(file);
            file.Close();

            ASCIIEncoding enc = new ASCIIEncoding();
            return enc.GetString(retVal);
        }
Avatar billede bvli Praktikant
22. september 2009 - 13:22 #1
Laver du alt i den samme tråd, eller sætter du en worker-tråd til at beregne md5'en på filerne?

Du behøver ikke alve en ny encoding hver gang. Brug i stedet den statiske "Encoding.ASCII". Det samme med din MD5CryptoServiceProvider. Den bruger iøvrigt com-interop mod OS'et, så det kan måske endda være den der bøvler.

Brug evt. en using(Stream file = File.OpenRead(fileName))
{
  //md5stuff.
}

så du er sikker på at lukke filen selvom din cryptoprovider smdier en exception.
Avatar billede Red0z Nybegynder
22. september 2009 - 14:29 #2
Ny kode, den ser sådan her ud, den kan køre bedre end den anden, men crasher stadig, hvad sagde du med MD5CryptoServiceProvider(); ? Hvad er com-interop? :)

Og hvis det kan være dét der crasher programmet, er der så en mere stabil og effektiv måde at lave MD5 hashs fra filerne ? :)

        protected string MD5HashFromFile(string fileName)
        {
            using(Stream file = File.OpenRead(fileName))
            {
                Encoding ascii = Encoding.ASCII;
                MD5 md5 = new MD5CryptoServiceProvider();
                Byte[] encodedBytes = md5.ComputeHash(file);
                ASCIIEncoding enc = new ASCIIEncoding();

                file.Close();
                return enc.GetString(encodedBytes);
            }
        }
Avatar billede bvli Praktikant
22. september 2009 - 15:25 #3
enten implementer IDisposable og:

  private MD5 md5 = new MD5CryptoServiceProvider();
  private bool disposed;
  protected string MD5HashFromFile(string fileName)
        {
            using(Stream file = File.OpenRead(fileName))
            {
                Byte[] encodedBytes = md5.ComputeHash(file);
                return Encoding.ASCII.GetString(encodedBytes);
            }
        }

  protected void Dispose(bool disposing) {
    if (!disposed) {
      if (disposing && md5 != null) {
        md5.Dispose();
      }
      disposed = true;
    }
  }

  public void Dispose() {
    Dispose(true);
    GC.SuppressFinalize(this);
  }


eller:

  protected string MD5HashFromFile(string fileName)
        {
            using(Stream file = File.OpenRead(fileName))
            using(MD5 md5 = new MD5CryptoServiceProvider())
            {
                Encoding ascii = Encoding.ASCII;
                Byte[] encodedBytes = md5.ComputeHash(file);
                return Encoding.ASCII.GetString(encodedBytes);
            }
        }
Avatar billede Red0z Nybegynder
22. september 2009 - 20:52 #4
Har nu fået indsat mulighed to i mit program, programmet kan køre mange flere filer igennem før den crasher, men 'ak' den crasher endnu. :/
Avatar billede bvli Praktikant
22. september 2009 - 21:23 #5
Humm.. mit gæt er, at du et eller andet sted ikke får ryddet op efter dig i den løkke, som itererer over filerne. Check om der er andre ting du bruger, som implementerer IDisposable og som du ikke får lukket. (læg dem i et using). Prøv evt. at implementere mulighed 1 i programmet, så du ikke skal lave en ny hashalgoritme hver gang. Den bruger som sagt operativsystemets funktioalitet, hvilket betyder den bruger COM.
Avatar billede arne_v Ekspert
23. september 2009 - 03:58 #6
Hvis du er på 3.5 kunne du prøve at erstatte MD5CryptoServiceProvider med MD5Cng !
Avatar billede Red0z Nybegynder
23. september 2009 - 08:22 #7
Får faktisk denne fejl lagde jeg lige mærke til, pingligt jeg ikke så det før.
--------------------------------------------------------------
FileCompare.exe!FileCompare.Form1.InsertButton_Click(object sender = {Text = Cannot evaluate expression because a native frame is on top of the call stack.}
--------------------------------------------------------------

Her er mit InsertButton_Click!

        public void InsertButton_Click(object sender, EventArgs e)
        {
            OrgGrid.Rows.Clear();
            DupGrid.Rows.Clear();

            List<string> md5list;
            string path = folderBrowse.SelectedPath;

            if (!Directory.Exists(path))
            {
                MessageBox.Show("You must choose a valid path first");
            }
            else
            {
                string[] filePaths = Directory.GetFiles(path, "*.wma",
                                        SearchOption.AllDirectories);

                md5list = new List<string>();

                foreach (string file in filePaths)
                {
                    filename = (file);
                    filedir = System.IO.Path.GetFullPath(file);
                    md5 = MD5HashFromFile(file).ToLower();
                    //richTextBox1.AppendText(path + "\n\n" + file);

                    if (md5list.Contains(md5))
                    {
                        DupGrid.Rows.Add(filename, file, md5);
                    }
                    else
                    {
                        //WriteToDoc();
                        OrgGrid.Rows.Add(filename, file, md5);
                        md5list.Add(md5);
                        richTextBox1.AppendText(file + "\n\n");
                    }
                    //richTextBox1.AppendText("\n\nMD5Array: " + md5 + "\n\n");

                }
            }
        }

Er det en gang rod jeg har lavet, eller ? :)
Avatar billede Red0z Nybegynder
23. september 2009 - 09:37 #8
Og har prøvet MD5Cng, den arbejder lidt hurtigere, men laver stadig stacking tror jeg :)
Avatar billede bvli Praktikant
23. september 2009 - 12:09 #9
Får du ikke andet i din fejlmeddelelse? linienummer eller lign.? Kører du i release-mode eller debug? Hvis du ikke kører i debug, så prøv at gøre det, og check om ikke fejlmeddelelsen er mere sigende. Hvor mange filer når du at få igennem?

Noget andet - når du får det til at virke, så ville jeg mene, at du skullle smide løkken ind i en separat metode, og så implementere den i en backgroundworker. Så vil dit GUI virke responsivt.
Avatar billede Red0z Nybegynder
23. september 2009 - 12:53 #10
Har aldrig prøvet at arbejde med en Background worker, men det ville være fantastisk at lære da jeg kunne bruge det i et par andre programmer jeg har lavet.

Fejlen kommer både i release og debug mode, og den kommer i

        public string MD5HashFromFile(string filename)
        {
            using (Stream file = File.OpenRead(filename))
            using (MD5 md5 = new MD5Cng())
            {
                Byte[] retVal = md5.ComputeHash(file); <-- HER!
                return Encoding.ASCII.GetString(retVal);
            }
        }

i Byte[] retVal = md5.ComputeHash(file); linien.

Og den fejl jeg kan finde står her:

      FileCompare.exe!FileCompare.Form1.InsertButton_Click(object sender = {Text = Cannot evaluate expression because a native frame is on top of the call stack.}, System.EventArgs e = {X = 29 Y = 13 Button = Left}) Line 80 + 0x22 bytes    C#
Avatar billede bvli Praktikant
23. september 2009 - 14:26 #11
ok - det siger mig ikke noget må jeg sige. Som skrevet ovenfor, prøv at lave en enkelt instans af din HashAlgoritm. (version 1 af de to eksempler jeg gav i går)

Det vil nok blive sværere at debugge, hvis du begynder at lægge det ind i en baggrundstråd nu. Senere kan du jo altid prøve at søge google for BackgroundWorker tutorial.
Avatar billede Red0z Nybegynder
23. september 2009 - 15:06 #12
protected void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing && md5 != null)
                {
                    md5.dispose(); <-- ERROR 1
                }
                disposed = true;

Error    1    'string' does not contain a definition for 'dispose' and no extension method 'dispose' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)    C:\Users\Kimlar\Documents\Visual Studio 2008\Projects\FileCompare\FileCompare\Form1.cs    30    25    FileCompare

Så kan ikke få det helt med . :)
Avatar billede bvli Praktikant
23. september 2009 - 15:11 #13
Du skal være opmærksom på, at du allerede har en dispose, da du har implementeret din kode i en Form. Så du kan bare hoppe ind i din eksisterende dispose og lave en:

if (md5 != null) md5.Dispose();

md5 skulle meget gerne være en instans af din CryptoProvider, ikke en string. Og du skal huske at Dispose er med stort d.
Avatar billede Red0z Nybegynder
23. september 2009 - 15:22 #14
Error    1    'System.Security.Cryptography.HashAlgorithm.Dispose(bool)' is inaccessible due to its protection level

Er fejlen jeg får ved dette. :) hvad kan det komme af ? :)
Avatar billede Red0z Nybegynder
23. september 2009 - 15:26 #15
Og istedet for .Dispose(); er md5.Clear(); ikke en mulighed? :)
Avatar billede bvli Praktikant
23. september 2009 - 16:24 #16
Bare Dispose() (uden parametre) :)

I øvrigt har jeg et konsolprogram til at køre - og som nu har kørt halvanden time - som laver det samme som dit program. Det har altså ikke brækket sig endnu. Hvor lang tid går der ca. før dit program går ned? Og har du ikke evt. en stacktrace eller lign?
Avatar billede Red0z Nybegynder
24. september 2009 - 08:00 #17
Kunne det have noget at gøre med at jeg bruger det i Windows.Forms ? frem for console ?
Avatar billede bvli Praktikant
24. september 2009 - 10:32 #18
Jeg skal ikke udelukke, at det kan have indflydelse. F.eks.  kører jeg ikke [STAThread] i mit lille eksempel.

Men jeg kommer til at tænke på, at du jo smider dit bytearray direkte ind i din kontrol på din form. Inklusive eventuelle nonprintable chars. Kunne det ikke have noget med det at gøre?

Prøv evt. at starte en Visual Studio Commando Prompt op, gem følgende kode som "Program.cs" og kør:

csc Program.cs

afvikl programmet Program.exe c:\sti\til\dine\filer

Og se om det også går ned.

--
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;

namespace B.Testing.Md5
{
    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();
            p.Start(args);
        }

        private void Start(string[] args)
        {
            string directoryName = args[0];
            if (!Directory.Exists(directoryName))
            {
                throw new DirectoryNotFoundException(directoryName);
            }
            string[] files = Directory.GetFiles(directoryName, "*.*", SearchOption.AllDirectories);
            foreach (string file in files)
            {
                Console.WriteLine(string.Format("file: {0}, MD5: {1}", file, MD5HashFromFile(file)));
            }
        }

        private string MD5HashFromFile(string filename)
        {
            using (Stream file = File.OpenRead(filename))
            using (HashAlgorithm md5 = new MD5CryptoServiceProvider())
            {
                Byte[] hash = md5.ComputeHash(file);
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < hash.Length; i++) {
                    //Konverter til hex-string.
                    sb.Append(hash[i].ToString("x2"));
                }
                return sb.ToString();
            }
        }
    }
}
Avatar billede Red0z Nybegynder
24. september 2009 - 10:42 #19
Ved test af det du har sat op her, kører programmet så glat som det skal. Så måske skulle jeg skrive det om, og prøve at lære at lave en background worker måske?

Og som du siger med at smide det direkte i kontrol med char's der ikke kan læses, det er også rigtigt.. så .. Ja. Måske må jeg lige prøve at starte lidt forfra. :)
Avatar billede bvli Praktikant
24. september 2009 - 10:53 #20
Prøv at starte med at implementere den version af Md5HashFromFile(string) som jeg bruger. Jeg har en mistanke om, at det skulle være det.

At lave det om til backgroundworker behøver ikke betyde at du skal skrive det om. Som sagt før, prøv at søge på en tutorial på backgroundworker på google.
Avatar billede Red0z Nybegynder
24. september 2009 - 13:11 #21
Programmet kører helt igennem, men viser stadig de samme fejl, altså at det crasher, så for at få den glatteste måde at køre programmet på, skal den så køre via BGworker? :)
Avatar billede Red0z Nybegynder
24. september 2009 - 13:12 #22
Og det jeg mener med det crasher er, at det gør det samme som sidst. :) Men hvis man lader det stå i lidt tid, kører det færdigt. :)
Avatar billede bvli Praktikant
24. september 2009 - 13:41 #23
Er du sikker på at det crasher? Jeg mener, hvis det crasher sådan rigtigt, så stopper det jo helt. Hvis du får en dialogbox fra Visual Studio med din fejlmeddelelse, kunne det jo reelt være en besked om, at den ikke kan vise det i debuggeren den gerne vil.

Hvad sker der hvis du kører exefilen direkte fra din explorer? Og jeg må ærligt erkende, at jeg må give op her, hvis ikke jeg har en rigtig fejlmeddelelse at forholde mig til.
Avatar billede Red0z Nybegynder
24. september 2009 - 13:46 #24
Du må undskylde hvis jeg er meget underinformativ da jeg er lidt af en rookie .. :)

Altså. Nu kører programmet. :) Men den skriver (Not responding) i windows når jeg kører .exe filen. :) Dog hvis man lader den stå, så kører den faktisk i baggrunden. Men man skal vente til at den har kørt programmet igennem før at den viser resultatet. :) så på sin vis kører det nu. Og prøver at se om jeg kan få lavet en Backgroundworker med den, så det kommer til at se mere naturligt ud . :)
Avatar billede bvli Praktikant
24. september 2009 - 13:53 #25
Ah.. Jamen så er alt jo godt. (Not responding) er nemlig præcis det der sker, hvis du kører tidskrævende operationer i din GUI-tråd. Derfor bør du bruge backgroundworkeren. God fornøjelse :)

Jeg satser på, at det er ok, at jeg smider et svar?
Avatar billede Red0z Nybegynder
24. september 2009 - 13:56 #26
Helt klart, tusinde tak for hjælpen! det er sku' fedt at jeg endelig fandt en side hvor folk er hurtige til at hjælpe ! :)
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