Witam. Jestem początkujący i mam pytanie odnośnie BackgroundWorker'a. Chodzi o to czy jeśli zniszcze (Dispose) obiekt w którym stworzyłem inny obiekt a w nim BackgroundWorkera to czy ten ten BackGroundWorker automatycznie się przerwie? Działa on w pętli nieskończonej monitorując kontrolki, które są UserControl. Na mocnym procku (i7) jest wszysytko ok. Problem jest na słabszym bo program obciąża mocno procesor (90 %). I nie zmienia się to nawet jeśli zniszczę UserControl. Wiem że mogę go przerwać (CancelAsync), ale muszę mieć bezpośredni dostęp do zmiennej backgroundworkera a z tym trochę gorzej.
nie. Pętla metody DoWork nie powinna być nieskończona. Powinieneś przynajmniej sprawdzać czy wątek nie został zastopowany metodą CancelAsync
przez sprawdzanie właściwości CancellationPending
, przykład https://msdn.microsoft.com/pl-pl/library/system.componentmodel.backgroundworker.cancellationpending(v=vs.110).aspx
BTW jak Twój wątek obciąża procesor na 90% a nie wykonuje jakichś skomplikowanych zadań to masz w nim coś zwalone.
To jest pętla nieskonczona która przechodzi po wszystkich Burtona w danym panelu i porównuje dane z baza. Czyli są tam dwie pętle ta wewnątrz to foreach i ona sprawdza każdy button. Jak zwiększyłem thread.sleep to problem obciążenia zniknal
bg raczej nie zakończy się sam, spróbuj coś takiego:
przy pętli nieskończonej dodaj sprawdzanie czy bacground
class FakeComponet : IDisposable
{
private BackgroundWorker bg = new BackgroundWorker();
public FakeComponet()
{
bg.WorkerSupportsCancellation = true;
bg.WorkerReportsProgress = true;
bg.DoWork += Bg_DoWork;
bg.ProgressChanged += Bg_ProgressChanged;
}
private void Bg_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
Console.WriteLine(e.UserState);
}
public void StartAsync()
{
bg.RunWorkerAsync();
}
private void Bg_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
while (true)
{
if (worker.CancellationPending)
{
e.Cancel = true;
break;
}
System.Threading.Thread.Sleep(1000);
worker.ReportProgress(0, DateTime.Now);
}
}
public void Dispose()
{
if (bg != null && bg.IsBusy)
{
bg.CancelAsync();
}
}
}
Powinno udać Ci się przeciążyć, albo zaimplementować Dispose dla komponentu który ma bg i tam to anulować. Bez tego, to raczej długo będzie bg działał.
Bardzo prosto to sprawdzić jak dasz sobie System.Console.Beep(); w pętli workera.
bg.CancelAsync();
NIC NIE DA jeśli nie obsłuży tego po stronie wątku
abrakadaber napisał(a):
bg.CancelAsync();
NIC NIE DA jeśli nie obsłuży tego po stronie wątku
Obsługa jest w wątku
if (worker.CancellationPending)
{
e.Cancel = true;
break;
}
rzeczywiście - nie zauważyłem.
Problem już rozwiązany. Jako że miałem kilka wątków to zrobiłem klasę singletona która zawiera listę wszystkich wątków. Po wyjściu z danego okna wywołuje dla wszystkich elementów listy CancelAsync.