Windows Forms Threading și evenimente - Lista de actualizări Lista prompt, dar bara de progres experiență întârziere uriașă

Echipa noastră creează un nou sistem de flux de recrutare pentru a înlocui unul vechi. Am fost însărcinat cu migrarea datelor vechi în noua schemă. Am decis să fac acest lucru prin crearea unui mic proiect Windows Forms, deoarece schema este radical diferită, iar scripturile TSQL drepte nu sunt o soluție adecvată.

Clasa principală sigilată "ImportController" care face lucrarea declară următorul eveniment delegat:

public delegate void ImportProgressEventHandler(object sender, ImportProgressEventArgs e);
public static event ImportProgressEventHandler importProgressEvent;

Fereastra principală începe o metodă statică în acea clasă folosind un fir nou:

Thread dataProcessingThread = new Thread(new ParameterizedThreadStart(ImportController.ImportData));
dataProcessingThread.Name = "Data Importer: Data Processing Thread";
dataProcessingThread.Start(settings);

arborele ImportProgressEvent poartă un mesaj șir, o valoare max int pentru bara de progres și o valoare curentă int curentă. Formularul Windows subliniază evenimentul:

ImportController.importProgressEvent += new ImportController.ImportProgressEventHandler(ImportController_importProgressEvent);

Și răspunde la eveniment în acest mod folosind propriul delegat:

    private delegate void TaskCompletedUIDelegate(string completedTask, int currentProgress, int progressMax);

private void ImportController_importProgressEvent(object sender, ImportProgressEventArgs e)
            {
                this.Invoke(new TaskCompletedUIDelegate(this.DisplayCompletedTask), e.CompletedTask, e.CurrentProgress, e.ProgressMax);
            }

În cele din urmă, bara de progres și lista de casete sunt actualizate:

private void DisplayCompletedTask(string completedTask, int currentProgress, int progressMax)
        {
            string[] items = completedTask.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);

            foreach (string item in items)
            {
                this.lstTasks.Items.Add(item);
            }

            if (currentProgress >= 0 && progressMax > 0 && currentProgress <= progressMax)
            {
                this.ImportProgressBar.Maximum = progressMax;
                this.ImportProgressBar.Value = currentProgress;
            }
        }

Lucru este lista pare să se actualizeze foarte repede, dar bara de progres nu se mișcă până când lotul este aproape complet oricum ??? ce dă ?

0
fr hi bn

6 răspunsuri

Sunteți sigur că firul UI rulează liber în timpul acestui proces? adică nu este așezat blocat în legătură cu o alăturare sau o altă așteptare? Asa arata mie.

Sugestia de a utiliza BackgroundWorker este una buna - cu siguranta superioara incercarii de a sansa - ciocandu-va drumul in afara problemei cu o incarcatura de apeluri de actualizare/actualizare.

Și BackgroundWorker va folosi un fir de bazin, care este un mod mai prietenos de a se comporta decât a crea propriul fir de scurtă durată.

0
adăugat

Nu există nici un câștig de la cumpărăturile de fire ca   Știu că se va produce vreodată unul   fir. Utilizarea unui fir este pură   pentru a avea un interfață utilizator receptivă în timp ce SQL   Serverul este încurcat cu citirile și   scrie. Cu siguranță nu este un scurt   a trăit fir.

OK, apreciez asta și mă bucur că ți-ai găsit bug-ul, dar te-ai uitat la BackgroundWorker? Ea face exact ceea ce faci, dar într-o manieră standardizată (adică fără propriii delegați) și fără a fi nevoie să creați un fir nou - ambele fiind avantaje (poate mici, dar poate încă utile).

0
adăugat

Poate în afara domeniului de aplicare, dar uneori este util să faceți un Application.DoEvents (); pentru a face părțile gui să reacționeze la intrarea utilizatorului, cum ar fi apăsarea butonului de anulare într-o fereastră de dialog de stare.

0
adăugat

@Ioan

Multumesc pentru link-uri.

@Voi

Nu există nici un câștig de la threadpooling, deoarece știu că va da vreodată un fir. Utilizarea unui fir este pur și simplu pentru a avea un interfață de răspuns rapid, în timp ce serverul SQL este folosit pentru citire și scriere. Cu siguranță nu este un fir scurt de viață.

În ceea ce privește ciocanele pentru sani ai dreptate. Dar, după cum se pare, problema mea era între ecran și scaun. Se pare că am un lot de date neobișnuit care are multe multe și mai multe înregistrări de chei străine decât celelalte loturi și se întâmplă doar să fie selectate la începutul procesului, ceea ce înseamnă că actualulProgress nu obține ++ 'd timp de 10 secunde.

@Toate

Mulțumesc pentru toate informațiile pe care le-ați primit, m-au făcut să mă gândesc, ceea ce ma făcut să mă uit în altă parte a codului, ceea ce a condus la momentul meu de umilință, când am dovedit încă o dată că eroarea este de obicei umană :)

0
adăugat

Încercați să executați Windows Vista? Am observat exact același lucru în unele aplicații legate de muncă. Cumva, pare să existe o întârziere atunci când bara de progres "animă".

0
adăugat
0
adăugat