Vă mulțumim pentru susținere

Este posibil să se "spioneze" mai multe fire GUI? (Nu oprirea sistemului la Application.Run)

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

  1. Aplicația începe.
  2. Verificați fișierul de configurare pentru încărcarea componentelor. Încărcați-le.
  3. Pentru fiecare componentă, executați DoStuff () pentru ao inițializa și a face să trăiască propria sa viață în firele proprii.
  4. 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 () ?

0
adăugat editat

3 răspunsuri

Sunt sigur că acest lucru este posibil dacă vă hackați destul de greu, dar aș sugera că nu este o idee bună.

"Windows" (pe care le vedeți pe ecran) sunt foarte cuplate la procese. Adică, fiecare proces care afișează orice interfață grafică se așteaptă să aibă o buclă de mesaje, care procesează toate mesajele care sunt implicate în crearea și gestionarea ferestrelor (lucruri precum "a făcut clic pe buton", "a închis aplicația", "a redesenat ecranul ' si asa mai departe.

Din acest motiv, se presupune mai mult sau mai puțin că, dacă aveți o buclă de mesaje, aceasta trebuie să fie disponibilă pentru întreaga durată a procesului. De exemplu, ferestrele ar putea să vă trimită un mesaj de tip "quit" și trebuie să aveți o buclă de mesaje disponibilă pentru ao gestiona, chiar dacă nu aveți nimic pe ecran.

Cel mai bun pariu este să faceți așa:

Faceți o formă falsă care nu este afișată niciodată, care este "aplicația principală" Lansare Apel Cerere.Run și treceți în această formă falsă. Lucrați într-un alt fir și faceți foc de la firul principal atunci când trebuie să faceți lucruri Gui.

0
adăugat
De fapt, ferestrele sunt cuplate la fire, nu la procese. Puteți avea mai multe bucle de mesaje pe proces și vă va permite să aveți mai multe ferestre complet independente.
adăugat autor Garo Yeriazarian

Application.Run method displays one (or more) forms and initiates the standard message loop which runs until all the forms are closed. You cannot force a return from that method except by closing all your forms or forcing an application shutdown.

You can, however, pass an ApplicationContext (instad of a new Form()) to Application.Run method and ApplicationContext can be used to launch several forms at once. Your application will only end when all of those are closed. See here: http://msdn.microsoft.com/en-us/library/system.windows.forms.application.run.aspx

De asemenea, toate formele pe care le afișați non-modal vor continua să fie difuzate alături de forma principală, ceea ce vă va permite să aveți mai multe ferestre care nu se blochează reciproc. Cred că asta este ceea ce încercați să realizați.

0
adăugat

Nu sunt sigur dacă acest lucru este corect, totuși îmi amintesc că rulează formulare de ferestre dintr-o aplicație de consolă doar prin redarea formularului și a apelarea lui newForm.Show () pe el, dacă componentele tale utilizează în locul aplicației Application.Run () forma nu ar trebui să blocheze.

Desigur, componenta va fi responsabilă pentru menținerea unei referințe la formele pe care le creează

0
adăugat