Der UI-Thread wird eingefroren, weil Sie eine System.Windows.Forms.Timer
verwenden, die das tickergesteuerte Timer-Ereignis auf dem UI-Thread auslöst; Dies ist nützlich, weil Sie keine Invoke
irgendetwas auf dem Tick-Ereignis haben. Der Aufruf von Join
blockiert den aufrufenden Thread und in Ihrem Fall ist dies der UI-Thread.
Um dies zu vermeiden (und da Sie nicht zu Invoke
keine UI-Elemente benötigen), können Sie Ihre System.Windows.Forms.Timer
zu einem System.Timers.Timer
, die aus dem UI-Thread trennen in einem Thread läuft ändern. Wenn Sie zu einem System.Timers.Timer
wechseln, müssen Sie einige der Syntax in Ihrem Code ändern (z. B. das Tick
-Ereignis ist das Elapsed
-Ereignis stattdessen usw.).
dort ist auch die System.Thread.Timer
und die System.Web.UI.Timer
, zusätzlich könnte man auch einen zweiten Thread Laichen aus dem Timer-Tick-Ereignisse innerhalb des UI-Thread auf dem Gewinde zu vermeiden warten, Beispiel:
private void timerEventHanlder(object sender, EventArgs e)
{
(new System.Threading.Thread(() => {
List<String> excels = getExcels();
if (!isRunning){ //in case previous timer even is not finished wait another 20 minutes...
isRunning=true; //flag to true
inserting(excels);
}
})).Start();
}
einen Start new thread ändert den aktuellen Code nicht und ermöglicht es Ihnen, ihn zu ändern, wenn Sie jemals etwas in der Benutzeroberfläche aufrufen müssen.
Sie beantworten sind andere Frage aber:
ich auch nicht wissen, was passieren würde, wenn ich mehr als 100 Dateien haben und aus diesem Grund mehr als 100 Threads. Würde das eine Speicherausnahme oder eine andere Ausnahme verursachen?
Laichen 100+ Threads werden keine Ausnahmen verursachen, wenn Ihr Code eine spezifische Ausnahme hat (wie ein Null-Delegierten als ThreadStart
bestanden), oder wenn das Betriebssystem nicht einen Thread erstellen, die, wenn das Betriebssystem kann Wenn du einen Thread erstellst, hast du größere Probleme. Es ist möglich, dass Speichererschöpfung auftreten kann, da das Thread
ein verwaltetes Objekt ist und daher Speicher belegt (zusammen mit einem ArrayList
, aber die Speichermenge für 100+ Threads (sogar 1000+) ist auf jedem System, das ausgeführt werden kann, vernachlässigbar Das .NET-Framework (selbst auf den meisten Embedded-Systemen), so dass die Anzahl der Threads nicht unbedingt ein Problem sein wird.
Mit Blick auf Ihren Code, möchten Sie möglicherweise anstelle von 100+ Threads, die Verwendung der System.Threading.ThreadPool
und ein System.Threading.CountDownEvent
, Beispiel:
CountdownEvent Countdown;
void LoadExcelData(object data)
{
// loads excel data to global array "Weather" which is used later on
Countdown.Signal();
}
//Execute every 20 minutes (Timer). Do not Execute in case previouse run is not finished
void inserting(List<object> excels)
{
Countdown = new CountdownEvent(excels.Count);
int i = 0;
while (i < excels.Count) {
ThreadPool.QueueUserWorkItem(LoadExcelData, excels[i++].File_name);
}
Countdown.Wait();
InsertToDB(WeatherList); //insert data which was read from Excels
isRunning = false; //Data was successefully inserted to DB
}
Dies wird das System-Thread-Pool nutzen, um Ihre Funktionen auszuführen und ermöglicht .NET handl e die Planung der Threads, um massive Ressourcenkonflikte zu vermeiden, wenn die Anzahl der Threads sehr hoch ist. Sie können andere Methoden verwenden, um zu blockieren, wie eine Mutex
oder Semaphore
, aber die CountDownEvent
kapselt ziemlich viel, was Sie mit anderen warten-Objekten tun müssten und die Threads aus dem Thread-Pool beitreten.
Um ehrlich zu sein, da Sie Daten aus Excel-Dateien in mehreren Threads lesen, wenn nicht jeder Thread den gesamten Inhalt der Datei in RAM liest und die Operationen auf diese Weise ausführt, sehen Sie möglicherweise keine enorme Leistungssteigerung . Multi-Threaded-Anwendungen mit schwerem E/A sehen normalerweise keine große Leistungssteigerung, es sei denn, die E/A befindet sich auf leistungsorientierten Geräten oder die erste Eingabe der gesamten Datei wird in den Arbeitsspeicher gelesen. Nur eine Randnotiz, da Sie mit Dateien multi-threading sind.
Es sollte auch beachtet werden, dass die Verwendung der System.Threading.ThreadPool
ideal für Threads ist, die Sie erwarten, nur für ein paar Sekunden oder so zu laufen; Wenn Sie erwarten, dass ein Thread länger dauern kann, sollten Sie bei der Erstellung der Threads bleiben, wie Sie es jetzt tun. Sie können immer noch die CountDownEvent
verwenden und Sie brauchen kein Array von Threads wie Sie haben (Sie könnten einfach die (new Thread(function)).Start()
Syntax verwenden).
Hoffe, dass kann helfen
Persönlich verwende ich kaum jemals Threads aus Gründen der Leistung. Ich benutze sie fast immer, um die Benutzeroberfläche ansprechbar zu halten. Eigentlich denke ich Threads _reduce_ die Leistung, aufgrund der Cross-Thread-Kommunikation overhand und Sperren/Synchronisieren. –
Von Anfang an habe ich das für die gleiche Sache gemacht - GUI war eiskalt. Aber dann musste ich wissen, wann alle Threads wegen des Timers beendet sind und ich habe das thread.Join() Event benutzt, welches die GUI wieder einfrieren ließ. Leistung verbessert in meinem Fall, weil zwei (oder mehr) Excel-Datei schneller verarbeitet werden. – michael24B