Entwickler-Ecke

Sonstiges (.NET) - Wie kann ich drei Methoden gleichzeitig laufen lassen


doubleII - Fr 14.07.17 14:07
Titel: Wie kann ich drei Methoden gleichzeitig laufen lassen
Hallo zusammen,

ich habe folgende Frage:

Ich nutze drei kamera.
Wenn ich Bilder gespeichert will, rufe ich die drei Methoden auf. Alles ganz einfach.
image1.Save(name der path)
image2.Save(name der path)
image3.Save(name der path)

Ich möchte aber die drei Methoden gleichzeitig aufrufen, um Zeit zu sparen.


hier ein Beispeil

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
// hier rufe ich die save method
pivate void btnSave(obejct sender, EventsArg e)
{
   Task.Run(() => {Save_Image().Wait();});  
}

 private async Task Save_Image()
        {
            string path = Environment.ExpandEnvironmentVariables
                             ($@"C:\Temp\Images\00000000_SVB_");
            try
            {
                IEnumerable<Task> task = Enumerable.Range(03).
                   Select(i => Task.Run(async () =>
                   {
                       if (i == 0)
                       {
                           await Image1(path + "0.bmp");

                       }
                       else if (i == 1)
                       {
                           await Image2(path + "1.bmp");

                       }
                       else if (i == 2)
                       {
                           await Image3(path + "2.bmp");

                       }
                   }));
                await Task.WhenAll(task);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, ex.StackTrace);
            }
            Console.WriteLine($"############## Save_Image function. #####################");
        }
        private async Task Image1(string path)
        {
            bool b = false;
            CurrentThread = Thread.CurrentThread;
            await Task.Run(() =>
            {
                b = image1.SaveImage(path + "");
                Console.WriteLine($"Image 1 saved: {b}. Thread : {CurrentThread.ManagedThreadId}");
            });
            
        }

        private async Task Image2(string path)
        {
            bool b = false;
            CurrentThread = Thread.CurrentThread;
            await Task.Run(() =>
            {
                b = image2.SaveImage(path);
                Console.WriteLine($"Image 2 saved: {b}. Thread: {CurrentThread.ManagedThreadId}");
            });
            
        }

        private async Task Image3(string path)
        {
            bool b = false;
            CurrentThread = Thread.CurrentThread;
            await Task.Run(() =>
            {
                b = image3.SaveImage(path);
                Console.WriteLine($"Image 3 saved: {b}. Thread : {CurrentThread.ManagedThreadId}");
            });
            
        }


Synchron habe ich auch probiert.
Ich bekomme immer die selbe Ergebnisse.
Save ohne Thread. Wenn ich die drei Methode nach einander aufrufe, bekomme ich
~ 60 ms;
eine image.Save(); dauert ungefähr 20 ms;

Save mit threads erwarte ich eine Zeit ungefähr 20 ms.
Nach der Messung bekomme ich aber wieder 60 ms.

Hat jemand eine Ahnung woran liegt es und was mache ich falsch.

Danke :)


Holgerx - Fr 14.07.17 14:15

Hmm..

Schonmal daran gedacht, das hier die Geschwindigkeit der Festplatte die Bremse ist?

Wenn die Platte (z.B.) zum Speichern von 6 MB (3 Dateien a 2 MB) ca 60 ms braucht, dann ist es egal, ob Du die 3 Dateien gleichzeitig (und damit nur jeweils langsamer) oder hintereinander (jeweils mit der vollen Schreibgeschwindigkeit) speicherst. Es dauert immer noch die 60 ms...

;)


Ralf Jansen - Fr 14.07.17 15:12

Potentiell sollte es sogar länger dauern wenn man es nicht einfach serialisiert.

a.) Es kann immer nur einer schreiben (physisch) es wäre eh nur Pseudoparalle und
b.) sollte es im Pseudoparallelen Fall beim schreiben zu häufigen Wechseln der Schreiber kommen muß jedesmal der Schreibkopf neu positioniert werden. Das erzeugt Overhead und bei rotierenden Platten ist der nicht unerheblich. Letztlich hast du Glück das Windows das weiss und deine Writes gebuffert hat so das die wieder halbwegs optimal nacheinander auf die Platte geschrieben werden ohne viel Schreibkopfumpositionierung so das es zumindest nicht langsamer wird.


doubleII - Fr 14.07.17 15:31

hhhmmm okay.
also das heiss, dass ich damit leben muss?


Ralf Jansen - Fr 14.07.17 16:07

Du könntest auch so viele Platten kaufen wie du Bilder parallel speichern willst. Das ginge auch.


doubleII - Fr 14.07.17 16:12

ja ok danke aber so was habe ich leider nicht.


wenn ich mehrere Datei kopiere und wieder speiche, wie werden sie in der Festplatte gespeichert, eine nach einander oder?


Ralf Jansen - Fr 14.07.17 17:01

Zitat:
wenn ich mehrere Datei kopiere und wieder speiche, wie werden sie in der Festplatte gespeichert, eine nach einander oder?


Ja Windows versucht das soweit wie möglich mit ganz wenig Kontextwechseln wechseln seriell auf die Platte zu schreiben. Das hat aber Grenzen.

Versuch mal in einzelnen gleichzeitigen Kopieraktionen (nicht mehrere Files markieren und einmal kopieren) aus dem Explorer heraus eine handvoll Isos ins gleiche Ziel Volume zu kopieren. Auf eine rotierenden Platte wird sich die Leistung mit steigender Anzahl Kopierjobs nicht nur aufteilen sondern der Overhead wird die Leistung gegen recht schnell gegen null drücken.