2013-11-04 16 views
12

Muszę być w stanie nieprzerwanie uruchamiać mój BackgroundWorker. Zdarzenie DoWork zawiera proces łączenia gwintów, a OnComplete aktualizuje mój interfejs użytkownika.Uruchamianie obiektu BackgroundWorker w trybie ciągłym

Nie byłem w stanie znaleźć sposobu na nieskończoną pętlę metody BackgroundWorker.RunWorkerAsync() bez zamrożenia całego programu. Każda pomoc będzie bardzo ceniona.

+1

Co chcesz zrobić ze swoim 'BackgroundWorker'? Dlaczego chcesz, aby działał nieprzerwanie? –

+1

Dlaczego po prostu nie używać "regularnego" gwintowania? A może zadania lub cokolwiek .. Dlaczego dokładnie potrzebujesz BackgroundWorker? AFAIK, to nie miało być używane tak jak nigdy. – walther

+1

Możesz komunikować się z powrotem do głównego wątku (UI) i utrzymywać działanie BackgroundWorker przy pomocy ReportsProgress. – Paparazzi

Odpowiedz

23

Musisz wykonać pętlę w swojej metodzie DoWork. Aby zaktualizować swój interfejs, należy użyć metody ProgressChanged. Oto mały przykład jak to może wyglądać

public Test() 
    { 
     this.InitializeComponent(); 
     BackgroundWorker backgroundWorker = new BackgroundWorker 
      { 
       WorkerReportsProgress = true, 
       WorkerSupportsCancellation = true 
      }; 
     backgroundWorker.DoWork += BackgroundWorkerOnDoWork; 
     backgroundWorker.ProgressChanged += BackgroundWorkerOnProgressChanged; 
    } 

    private void BackgroundWorkerOnProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     object userObject = e.UserState; 
     int percentage = e.ProgressPercentage; 
    } 

    private void BackgroundWorkerOnDoWork(object sender, DoWorkEventArgs e) 
    { 
     BackgroundWorker worker = (BackgroundWorker) sender; 
     while (!worker.CancellationPending) 
     { 
      //Do your stuff here 
      worker.ReportProgress(0, "AN OBJECT TO PASS TO THE UI-THREAD"); 
     }   
    } 
+5

Zamiast 'while (true)' użyj '((BackgroundWorker) sender) .CancellationPending' i wspierasz anulowanie. – CodeZombie

+0

Aktualizuję mój kod wraz z częścią – Tomtom

+1

Logika musi być odwrócona. Anulowanie jest początkowo fałszywe i staje się prawdziwe, gdy użytkownik chce je anulować. Więc pętla powinna być sprawdzana '! Worker.CancellationPending' – Chris

-2

Jeśli program jest lodowata, to może być dlatego, że nieskończenie pętli pracownik tło wątek jest spinning, używając 100% CPU. Nie powiedziałeś, dlaczego potrzebujesz go uruchomić w nieskończonej pętli, ale możesz zacząć od umieszczenia Thread.Sleep w tej pętli.

+1

Thread.Sleep to zła praktyka i nie należy jej używać do produkcji. Problem wydaje się być inny podczas wykonywania pętli, na przykład być może podczas (true). Nawlekanie powinno być używane, gdy ma zostać uruchomione długie zadanie, a następnie zostanie zakończone. nie ma powodu, aby wątek działał, nawet jeśli zadanie zostało zakończone. musisz pozwolić, aby rzeczy "zdarzały się naturalnie", jak to mówią. –

+0

@Ahmedilyas - Nie sugerowałem wprowadzania czegokolwiek do produkcji. Myślę, że BackgroundWorker, który uruchamia nieskończoną pętlę, jest wątpliwą praktyką, ale umieszczenie Thread.leep może spowodować, że OP wykracza poza problem "zamrożenia aplikacji", i do pozycji, aby myśleć więcej o jego projekcie. Nie powiedział, dlaczego chce nieskończonej pętli, więc trudno jest zasugerować, jakie rozwiązania mogłyby być bardziej odpowiednie. – Joe

+0

Należy pamiętać, że "nieskończona pętla" nie oznacza użycia 100% procesora, w ogóle w aplikacjach wielowątkowych - zazwyczaj blokują one coś. Ponadto, to wykorzystanie wątku. Spać jest rzeczywiście złe praktyki, ale ma uzasadnione zastosowania. –

4

Zrobiłem to w przeszłości, kiedy potrzebowałem czegoś do działania w tle. Jeśli spróbujesz uruchomić pracującego w tle, gdy jest on uruchomiony, dostaniesz wykrzyknik! Dlatego właśnie uruchamiam BackGroundWorker, gdy zakończy się to w ukończonym wydarzeniu.

A potem będzie pętla na zawsze.

private void Main_Load(object sender, EventArgs e) 
{ 
    // Start Background Worker on load 
    bgWorker.RunWorkerAsync(); 
} 

private void bgWorker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    Thread.Sleep(1000); // If you need to make a pause between runs 
    // Do work here 
} 

private void bgCheck_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
// Update UI 

// Run again 
bgWorker.RunWorkerAsync(); // This will make the BgWorker run again, and never runs before it is completed. 
} 
+1

Zamiast po prostu uruchamiać go w dowolnym momencie, to dlaczego nie ma po prostu pętli while (true), więc uruchamia się w nieskończoność? – bkribbs

+2

Pracował bez zarzutu! Jego wdrożenie było łatwiejsze niż odliczanie czasu i wykonuj swoje zadanie bez blokowania interfejsu użytkownika! Wielkie dzięki, świetna metoda :)! Powinien być oznaczony jako odpowiedź. –

+0

--bkribs Ponieważ w ten sposób można również dodać kod w "ProgressUpdated" i "WorkerCompleted", jeśli potrzebujesz zaktualizować elementy interfejsu użytkownika :) –

-1
timer.interval=60000 // 1 min 

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
     timer1.Start(); 

    } 
private void timer1_Tick(object sender, EventArgs e) 
    { 
     try 
     { 
      //Do something 
     } 
     catch 
     { 


     } 
    } 
+0

Zawsze dobrze jest dołączyć jakąś formę szczegółu lub opisu, dlaczego odpowiedź działa, a nie tylko kod. –

+1

Chociaż ten fragment kodu może rozwiązać pytanie, [w tym wyjaśnienie] (// meta.stackexchange.com/questions/114762/explaining-entirely-code-ans -answers) naprawdę pomaga poprawić jakość twojego posta. Pamiętaj, że odpowiadasz na pytanie przeznaczone dla czytelników w przyszłości, a te osoby mogą nie znać powodów sugestii dotyczących kodu. Proszę również nie tłumić kodu za pomocą komentarzy wyjaśniających, ponieważ zmniejsza to czytelność zarówno kodu, jak i objaśnień! – FrankerZ

Powiązane problemy