Static kann an vielen Stellen Sinn machen, sollte aber mit Bedacht genutzt werden, da static prinzipiell etwas gegen die Prinzipien der Objektorientierung arbeitet (z.B. der Zuweisung von Funktionalität an ein Objekt).

Static kann aber beispielsweise Sinn machen, wenn du ein Singlepattern implementieren möchtest. Ein Singletonpattern könnte z.B. wie folgt aussehen:

public class Singleton
  {
    public static Singleton Instance { get; }

    static Singleton()
    {
      Instance = new Singleton();
    }

    private Singleton()
    { }

    public void InstanceMethod1() => Console.WriteLine("Ich bin eine Instanzmethode");

    public void InstanceMethod2() => Console.WriteLine("Ich bin auch eine Instanzmethode");
  } 

Durch dieses Muster hast du immer eine nur genau eine Instanz der Singleton-Klasse (auf der Property "Instance"), da die Klasse nicht außerhalb von sich selbst instanziiert werden kann und sich selbst nur beim ersten Zugriff auf sie instanziiert (Eigenschaft des statischen Konstruktors: Er wird nur ein einziges Mal beim ersten Zugriff auf die Klasse durchlaufen). Diese eine Anwendungs-weite Singletoninstanz kannst du dann in der ganzen Anwendung wie folgt abrufen und dessen Instanzmethoden verwenden:

public void SingletonTest()
    {
      Singleton.Instance.InstanceMethod1();
    }

Static benutze ich außerdem häufig für "Toolbox"-Klassen - also Klassen die allgemeine Funktionen bereitstellen um mir das Leben zu vereinfachen und einfach immer aufrufbar sein sollen ohne das ich explizit eine Instanz der Klasse erstellen muss. Außerdem macht z.B. auch in Anwendungsfällen Sinn, wo du zählen möchtest, wie oft ein Objekt bereits initialisiert wurde.

Ein besonderer Anwendungsfall sind Extensionmethoden - also Methoden mit denen du vorhandene Klassen dessen Quellcode dir nicht vorliegt erweitern möchtest. Z.B. so:

public static class ListExtensions
  {
    public static void PrintAllItems<T>(this List<T> items)
    {
      foreach (var item in items)
        Console.WriteLine(item);
    }
  }

Dadurch schaffst du dir die Möglichkeit die Methode "PrintAllItems" auf allen Objekten vom Typ List<T> aufzurufen:

public void ExtensionTest()
    {
      var list = new List<string>();
      list.PrintAllItems();
    }

Es gibt bestimmt noch tausende Anwendungsfälle für static und auch viele bei denen man auf static verzichten sollte, jedoch sind das so die Fälle in welchen ich static oft verwende.

...zur Antwort

Erstens: Ja x86 steht für 32bit

Anstatt Windows 8 als Ersatz für Windows 10 installieren, würde ich den Fehlern bei der Installation von Windows 10 auf den Grund gehen.

Um auf Nummer sicher zu gehen würde ich mir an eurer Stelle mal eine frische Windows 10 ISO besorgen und damit nochmal Windows 10 installieren.

Dazu sind folgende Schritte nötig:
1. Das MediaCreationTool von Microsoft herunterladen
(https://www.microsoft.com/de-de/software-download/windows10)
2. Ein Windows 10 64Bit (x64) Installationsmedium erstellen
2.1. Im MediaCreationTool Lizenzbedingungen akzeptieren
2.2. "Installationsmedien (USB-Speicherstick, DVD oder ISO-Datei) für einen anderen PC erstellen)" wählen
2.3. Sprache auswählen, als Edition "Windows 10" und als Architektur 64-Bit auswählen (sollten sich die Einstellungen nicht ändern lassen, einfach den haken bei "Empfohlene Optionen für diesen PC verwenden" herausnehmen).
2.4. Einen USB-Stick einstecken
2.5. Den USB-Stick formatieren
2.6. Im MediaCreationTool "USB-Speicherstick" wählen
2.7. Den eingesteckten USB-Stick wählen und mit dem Klick auf "weiter" das Tool seinen Job machen lassen (könnte eine Weile dauern)

Bevor Ihr nun etwas anderes macht, solltet Ihr - falls noch nicht geschehen - euch den Aktivierungsschlüssel von Windows aufschreiben/abfotografieren, oder was auch immer. Habt ihr den Schlüssel nicht parat, könnt Ihr euch diesen mit dem Tool "ProduKey" aus der aktuellen Windowsinstallation auslesen.

Das MediaCreationTool hat nun das Installationsmedium auf den USB-Stick gepackt. Es muss also nur noch installiert werden. Dazu einfach den Rechner neustarten und beim Hochfahren mal das Bootmenü öffnen. Bei meinem Mainboard mache ich das, indem ich F12 spamme, bei dem von deinem Vater könnte das aber anders sein (z.B. F10). Einfach mal ausprobieren und im Zweifel in der Anleitung nachgucken.

Wenn Ihr im Bootmenü seid, wählt Ihr dort einfach den USB-Stick aus, welcher dann das SetUp von Windows lädt, sodass Ihr es wie gewohnt installieren könnt. Die Installation einfach wie gewohnt durchklicken - sollte ziemlich straight-forward sein - und das war es auch schon. Jetzt müssen natürlich nur noch alle Programme die dein Vater braucht installiert werden.

Wenn Ihr den Rechner nach einer frischen Installation nun neustartet und erneut das Windows-SetUp gestartet wird, solltet Ihr noch die Bootpriotität im BIOS prüfen. An erster Stelle sollte immer die Festplatte mit dem Betriebssystem bzw. der Windows Bootloader stehen.

Noch ein kleiner Hinweis:
64-Bit Installationen sind sogut wie immer sinnvoller vor allem in heutigen Tagen. Warum? Weil eine 64-Bit Installation auch mit 4GB Ram klar kommt und sowohl Anwendungen in 32-Bit, als eben auch Anwendungen in 64-Bit ausführen kann. 32-Bit Betriebssysteme können NUR 32-Bit Anwendungen öffnen.

...zur Antwort

Ich weiß nicht ob das die perfekte Lösung ist, jedoch könntest du dir eine Anwendung schreiben die genau dies tut und dir eine Aufgabe im Windows Aufgabenplaner erstellen, die deine Anwendung bei Systemstart startet. Alternativ zum Aufgabenplaner kannst du dir natürlich auch einen Dienst erstellen der automatisch startet, jedoch habe ich da keine Erfahrung mit.

Wie ein Programm aussehen könnte in dem du eine Mail versendest, hängt von der Programmiersprache ab, deshalb überlasse ich es dir selbst ein Beispiel in deiner Programmiersprache herauszusuchen.

Wie ich gelesen habe, könntest du die Anwendung in einer beliebigen .NET-Sprache oder gutem alten C/C++ schreiben. Ob es auch in anderen Sprachen möglich ist weiß ich nicht.

Als SMTP-Server + Port verwendest du dann den öffentlichen Server + Port deines Mailproviders. Hier ein Beispiel von web.de:https://hilfe.web.de/pop-imap/imap/imap-serverdaten.html

...zur Antwort

Zu aller erst würde ich das Betriebssystem neu installieren. Zwar sind deine Treiber vlt. auf dem aktuellsten Stand, aber ggf. sind auch noch Reste von vorherigen Treibern noch irgendwo installiert. Das ist aber nicht der einzige Grund. Eine frische Installation des Betriebssystems ist prinzipiell bei Fehlern wie deinem immer eine gute Idee um Softwareseitige Fehler auszuschließen. Außerdem sollte es jeden Versuch wert sein, bevor du Geld ausgeben musst um dir eine neue GPU zu kaufen.

Tritt der Fehler nach der frischen Installation immer noch auf würde ich mir an deiner Stelle mal einen GPU-Stresstest wie Furmark herunterladen (https://geeks3d.com/furmark/) und eine Weile zusammen mit GPU-Z oder HWMonitor im laufen lassen. Das sollte deine GPU so hoch es geht auslasten und dir somit zumindest einen Hinweis geben ob der Effekt z.B. hitzebedingt auftritt. Es macht allerdings keinen Sinn eine Anwendung wie Furmark 5 Minuten laufen zu lassen und dann schon festzulegen ob die GPU hinüber ist oder nicht. Eine Stunde macht da mehr Sinn.

Nach dem Stresstest kannst du folgende Resultate haben:

  1. Du bekommst auch in Furmark einen Blackscreen
  2. Nein in Furmark läuft alles super

Keins von beiden Resultaten ist alleine schon in irgendeiner Art und Weise aussagekräftig, sondern leitet nur in die Richtung in der der Fehler liegt.

Im ersten Fall, dass du auch in Furmark einen Blackscreen bekommst, würde ich mal einen Blick auf die Temperaturen werfen. Diese sollten unter dem Grenzwert deiner GPU bleiben (sollte auf dem Specsheet deiner Grafikkarte auf der Seite von AMD/NVidia zu finden sein). Übersteigt die Temperatur die Limits der Karte, kannst du versuchen z.B. die Lüfterkurve mal anzupassen oder die GPU vlt. testweise mal herunterzutakten. Anschließend solltest du den Test nochmal machen und schauen ob der Fehler wieder auftritt. Tritt der Fehler immer noch auf, kannst du mal etwas tiefer in die Materie gehen und z.B. das BIOS deiner GPU updaten (manche Modelle der GTX 1070 Reihe von NVidia mussten das z.B. machen da man sonst ggf. ein Problem mit den verbauten VRMs haben konnte). Außerdem könntest du noch das BIOS deines Mainboard updaten. Nach jeder Änderung sollte der Test natürlich fleißig wiederholt werden.

In dem zweiten Fall würde ich eher auf einen Fehler anderer Natur tippen. Du könntest mal einen CPU-Stresstest wie den in CPU-Z versuchen und auch dort mit HWMonitor die Temperaturen im Blick behalten. Ich glaube zwar nicht dass der Fehler aufgrund eines Problems mit dem RAM auftritt, jedoch kann auch ein Memtest nicht schaden.

Eine weitere Möglichkeit kann natürlich auch sein (wie schon @herja geschrieben hat), dass du die Karte mal in einem anderen System testest, bzw. mal eine andere Karte in dein System einbaust und testest. Außerdem kannst du auch mal nach diesem Problem in Kombination mit Komponenten deiner Hardware Googlen. Z.B.: "GTX 1070 blackscreen". Ggf. findest du dort irgendwo eine Lösung. Was aber auch schon hilfreich daran ist, ist die Information ob mehrere Leute das gleiche Problem mit der Karte haben.

Für mich hört sich der Fehler ehrlich gesagt nicht unbedingt nach einem Problem der GPU an. Spiele wie CS:GO und besonders alte Call of Dutys sind eher CPU statt GPU lastig (bei WOW habe ich leider keine Ahnung).

...zur Antwort

Wie bereits andere erwähnt haben, kannst du - sofern du nur lesend auf die Datei zugreifen willst - die Datei wie folgt öffnen:

Bild zum Beitrag

Durch FileAccess.Read sagst du aus, dass du nur lesend auf die Datei zugreifen möchtest, während du mit FileShare.ReadWrite aussagst, dass andere Anwendungen trotzdem in die Datei schreiben können.

Da ich in den anderen Antworten irgendwo gelesen habe, dass dein Programm die Datei "leider nicht direkt schließt", noch ein kleiner Ratschlag, falls du das nicht machst:

Gerade auf FileHandles bzw. Objekt die native Ressourcen verwenden, solltest du (sofern möglich) immer mit Using zugreifen. Using sagt aus, dass dein Objekt nur im aktuellen Scope vorhanden ist und garantiert beim verlassen des Scopes, dass die Funktion "Dispose()" auf dem erstellten Objekt aufgerufen wird. Dispose bei einem FileHandle kümmert sich z.B. darum den Handle zu schließen und die Datei wieder freizugeben. Using ist nur auf Objekten verfügbar die IDisposable implementieren. Dadurch kannst du Dispose auch selbst aufrufen, wenn es sich bei dem Objekt z.B. um einen Member eines anderen Objektes handelt.

...zur Antwort

Auch wenn du geschrieben hast, dass du keine ganze Webseite durchlesen willst, hier mal ein hilfreicher Link:
https://codewala.net/2015/07/29/concurrency-vs-multi-threading-vs-asynchronous-programming-explained/

Async & await sind relativ komplex und deshalb auch nicht "mal eben so erklärt"

Aber ein paar Worte von mir dazu:
Async & await ist kein Ersatz für Threads. Es dient einzig und alleine dazu, vorhandene Ressourcen (wie Threads) so gut es geht auszulasten.

Wie auf der Seite erklärt wird, kann ein Thread bei "normaler" (also synchroner) Programmierung immer nur einen Task nach dem anderen abschließen. Hast du z.B. eine grafische Oberfläche und möchtest bei dem Klick auf einen Button Daten in eine Datenbank speichern, kann das eine Weile dauern (vor allem wenn die Datenbank auf einer anderen Maschine liegt o.Ä.). Nun würde die Anwendung einfach solange einfrieren, bis die Funktionalität hinter dem Button abgeschlossen ist.

Bei gleichem Szenario, allerdings mit asynchroner Programmierung, hättest du dieses Problem nicht. Konkret:
Dein Button-Click-Handler würde als "async void" deklariert werden und mit await deine asynchrone Funktion zum Speichern der Daten aufrufen. Await bedeutet dann quasi, dass die Funktion genau an dieser Stelle pausiert, bis deine Funktion zum Speichern fertig ist, erst dann wird der Rest der Funktion durchlaufen. In der Zeit, in der auf die Rückmeldung der Funktion zum Speichern gewartet wird, kann sich dein Programm aber z.B. um das aktualisieren der Oberfläche kümmern, sodass diese nicht einfriert.

Weil ich das mit "async void" bei EventHandlern hier erwähnt habe:
EventHandler wie z.B.

MeinTollerButton1_Click(object sender,  EventArgs e)

sind die einzigen Funktionen, bei denen "async void" Sinn macht. Sonst sollte async nur verwendet werden, wenn ein Task oder ein Task<T> zurückgegeben wird. Der Grund ist, dass bei Funktionen mit dem Rückgabetyp void nicht festgestellt werden kann, ob die Funktion schon fertig ist, oder nicht.

Um also noch deine Frage zu beantworten, wie man async & await verwendet, hier ein kleines Beispiel:

Bild zum Beitrag

Ich habe hier zwar viel geschrieben aber dennoch nur einen Bruchteil der Besonderheiten und Vorteile von async & await aufgezählt. Wenn du genauere Details brauchst, wie z.B. warum async & await nicht für jede Funktion geeignet ist oder unter gewissen Umständen sogar die Performance verschlechtert, solltest du doch mal den einen oder anderen Artikel dazu lesen.
Sollte es nur am lesen scheitern, hier ein YouTube-Kanal der mir weitergeholfen hat:
https://www.youtube.com/user/IAmTimCorey/videos

...zur Antwort

Ich würde mal folgendes prüfen:

  • Ist deine config.cfg ggf. schreibgeschützt?
  • Verwendest du eine autoexec.cfg (um ggf. Einstellungen beim Start zu überschreiben)

Beide Dateien findest du unter folgendem Pfad:

<Steaminstallationsordner>/userdata/<ID deines Accounts>/730/local/cfg

...zur Antwort

Nein die Sprachen sind nicht gleichwertig. Alle Programmiersprachen bewirken mehr oder weniger das gleiche, jedoch spielt der Weg dahin eine große Rolle. Ein Ferrari ist ein Auto genau wie ein Opel, jedoch erreicht ein Ferrari seine Ziele ggf. schneller mit höheren Kosten.

Um mal etwas auszuholen:

C++ wird beispielsweise bei der Kompilierung direkt in Maschinencode übersetzt, weshalb der Code sehr schnell ist, jedoch ohne große Änderungen nur auf bestimmten Plattformen funktioniert.

Java und andere Sprachen wie C#, VB.NET, etc. werden hingegen nicht direkt in Maschinencode übersetzt sondern in eine Art Zwischensprache (auch Bytecode genannt). Dies ist der Code der im Endeffekt beim Ausführen dieser Anwendung ausgeführt wird. Da es sich aber noch nicht um Maschinencode handelt, kann der Code nicht direkt ausgeführt werden, sondern durchläuft vor dem erstmaligen Ausführen einen wichtigen Schritt: Die Umwandlung des Bytecodes in Maschinencode. Dabei kommt in den meisten Implementierungen von Java ein sogenannter Just-In-Time-Compiler zum Einsatz. Wie der Name schon sagt, wird auszuführender Code erst kompiliert, wenn er auch benötigt wird (deshalb kann es z.B. sein, dass eine Aktion in einer Java-Anwendung beim ersten Ausführen länger dauert als beim zweiten Mal).
Die Verwendung eines Just-In-Time-Compiler hat einen riesigen Vorteil: Dem Entwickler kann es vorsichtig gesagt "egal" sein, auf welcher Plattform seine Anwendung ausgeführt wird. Die auf dem Endgerät installierte Runtime sorgt plattformspezifisch dafür, dass der Bytecode entsprechend für die Plattform in den passenden Maschinencode umgewandelt wird. Nachteil bei diesem Vorgehen ist natürlich unter anderem die Performance.

Python ist nochmal etwas anderes, da es sich hierbei um eine Interpretersprache handelt. Hierbei wird der Code von Seiten des Entwicklers nicht in etwas anderes umgewandelt, sondern erst auf dem Endgerät in Maschinencode umgewandelt. Auch hierdurch ist Plattformunabhängigkeit gegeben, nur hat diese bei Interpretersprachen unter anderem einen höheren Preis der Performance. Der Unterschied zwischen Just-In-Time-Kompilierung ist, dass ein Interpreter Code bei Nutzung immer wieder aufs neue Kompiliert, während ein Just-In-Time-Compiler dies nur bei der ersten Nutzung tut.

Unter anderem lassen sich aus oben genannten Unterschieden auch gewisse Anwendungsgebiete herleiten. So macht es beispielsweise wenig Sinn einen performancekritischen Treiber in Python zu schreiben (mal abgesehen von der technischen Machbarkeit), während es aber gleichzeitig nur bedingt Sinn macht eine Businessanwendung mit intuitiver Oberfläche welche auf verschiedenen Plattformen verfügbar sein soll in C++ zu schreiben (da die Entwicklungszeit sich meist bei höheren Programmiersprachen kürzer hält als in low-level Sprachen wie C++).

Natürlich kann man die meisten Ziele in mehreren Sprachen erreichen und ein Entwickler kommt vlt. besser mit der einen Sprache als der anderen klar, aber prinzipiell gibt es jede Programmiersprache aus einem Grund der sich wie bereits erwähnt von verkürzten Entwicklungszeiten bis hin zu schlicht und einfach einer angenehmeren Syntax strecken kann.

...zur Antwort

Nein eine Klasse besitzt keine Objekte. Eine Objektinstanz besitzt Objekte.

Wie du schon sagst ist eine Klasse der Bauplan eines Objektes. Du verwendest also eine klasse um daraus ein Objekt zu erstellen, was auch Objektinstanziierung genannt wird.

Objektinstanzen werden erst zur Laufzeit erstellt, nicht zur Compilezeit.

Ein Beispiel von Objektinstanzen wäre wie folgt:
Du hast eine Klasse Tier mit den beiden Eigenschaften Farbe und Name. Nun erstellst du an irgendeiner Stelle in deinem Code ein neues Objekt dieser Klasse und vergibst Werte für die beiden Eigenschaften.
Nun kannst du aber von einer beliebigen anderen Stelle in deinem Code erneut ein neues Objekt der Klasse Tier erstellen und andere (oder die gleichen) Eigenschaften dafür vergeben. Damit hast du zwei unterschiedliche Objektinstanzen der gleichen Klasse.

...zur Antwort

Schau z.B. mal nach Selection- oder Bubblesort (damit habe ich angefangen programmieren zu lernen). Wie @KarlRanseierIII schon geschrieben hat, trifft die Bedingung "c == 0" in der zweiten Schleife niemals zu. Solltest du die Bedingung aber so ändern, dass sie zutrifft, könntest du in der nächsten Zeile ein Problem bekommen, da du mit "a[c]" auf einen index außerhalb des Arrays zugreift (denn c = n + 1 = 5).

Fehler wie diese könntest du umgehen, indem du beispielsweise IDEs wie Visual Studio (die Community-Edition ist für jeden kostenlos) verwendest.

Und noch ein kleiner Hinweis: Dein Algorithmus sorgt aktuell nur dafür, den kleinsten Wert in dem Array ans Ende und den größten Wert an den Anfang zu bringen. Änderst du also z.B. das zu sortierende Array auf [3, 3, 5, 8] ab, wird der Algorithmus nicht mehr funktionieren.

Eine mögliche Lösung nach dem Selectionsort-Muster könnte z.B. so aussehen:

int main() {
 int a[4] = { 3,3,5,8 };
 int n = 4;
 for (int left = 0; left < 4 - 1; left++)
  for (int right = left + 1; right < 4; right++) {
   if (a[left] < a[right]) {
    int tmp = a[left];
    a[left] = a[right];
    a[right] = tmp;
   }
  }
 return 0;
}
...zur Antwort