Obiectivul meu
Aș dori să am un fir de procesare principal (non-GUI) și să pot dezactiva GUI-urile în firele de fundal proprii, după cum este necesar, și să continui să continui firul meu principal non-GUI. Altfel, vreau ca firul meu principal non-GUI să fie proprietarul thread-ului GUI și nu invers. Nu sunt sigur că acest lucru este posibil chiar și în cazul Windows Forms (?)
Background
Am un sistem bazat pe componente, în care un controler dinamic încarcă ansambluri și instanțează și execută clase care implementează o interfață comună IComponent
cu o singură metodă DoStuff()
.
Ce componente se încarcă este configurată printr-un fișier de configurare xml și prin adăugarea de ansambluri noi care conțin diferite implementări ale IComponent
. Componentele oferă funcții de utilitate pentru aplicația principală. În timp ce programul principal se ocupă de acest lucru, de ex. controlând o instalație nucleară, componentele ar putea să îndeplinească sarcini utilitare (în firele lor), de ex. curățarea bazei de date, trimiterea de e-mailuri, imprimarea glumelor amuzante pe imprimantă, ce aveți. Ceea ce aș vrea este să aveți una din aceste componente să poată afișa o interfață grafică, de ex. cu informații de stare pentru respectiva componentă de trimitere a e-mailului.
Durata de viață a sistemului complet arată astfel
- Aplicația începe.
- Verificați fișierul de configurare pentru încărcarea componentelor. Încărcați-le.
- Pentru fiecare componentă, executați
DoStuff()
pentru ao inițializa și a face să trăiască propria sa viață în firele proprii.
- Continuă să faci regele principal al aplicației, pentru totdeauna.
Încă nu am reușit să realizez cu succes punctul 3 dacă componenta declanșează un GUI în DoStuff()
. Pur și simplu se oprește până când interfața grafică este închisă. Și nu până când interfața grafică este închisă, programul trece la punctul 4.
Ar fi minunat dacă aceste componente ar avea permisiunea de a-și lansa propriile GUI-uri Windows Forms.
Problemă
Când o componentă încearcă să declanșeze un GUI în DoStuff()
(linia exactă a codului este atunci când componenta rulează Application.Run (theForm)
), componenta și, sistemul nostru "se blochează" la linia Application.Run()
până când interfața grafică este închisă. Ei bine, doar GUI-ul funcționează bine, așa cum era de așteptat.
Exemplu de componente. Unul nu are nimic de a face cu GUI, în timp ce al doilea incendiază un ferestre drăguț cu iepurași roz pufos în ele.
public class MyComponent1: IComponent
{
public string DoStuff(...) { // write something to the database }
}
public class MyComponent2: IComponent
{
public void DoStuff()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form());
// I want the thread to immediately return after the GUI
// is fired up, so that my main thread can continue to work.
}
}
Am încercat asta fără noroc. Chiar și atunci când încerc să aprind GUI-ul în firul propriu, execuția se oprește până când interfața grafică este închisă.
public void DoStuff()
{
new Thread(ThreadedInitialize).Start()
}
private void ThreadedInitialize()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form());
}
Este posibil să separați un GUI și să reveniți după Application.Run()
?