2012-06-18 25 views
14

Czy można zdefiniować pracownika tła w metodzie?Pracownik w tle i wywóz śmieci?

private void DownLoadFile(string fileLocation){ 
    BackgroundWorker worker = new BackgroundWorker(); 

    worker.DoWork += new DoWorkEventHandler((obj, args) => { 
     // Will be executed by back ground thread asynchronously. 
     args.Result = Download(fileLocation); 
    }); 

    worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler((obj, args) => { 
     // will be executed in the main thread. 
     Result r = args.Result as Result; 
     ReportResult(r); 
    }); 

    worker.RunWorkerAsync(fileLocation); 
} 

Pytanie: W przypadku pobierania function() zajmuje dużo czasu, aby pobrać plik, może GC kopać i zbierać obiekt pracownika przed RunWorkerCompleted() jest wykonywana?

+0

Polecam używanie delegata (działanie (z ciągów)), a następnie wywołanie BeginInvoke. Nie widzę potrzeby korzystania z BackgroundWorker w tym kodzie. Nadal można dołączyć wydarzenie, gdy metoda zostanie wykonana. – JDB

+1

Lepszym sposobem na to byłoby dodanie go do kolejki puli wątków za pomocą 'QueueUserWorkItem': http://msdn.microsoft.com/en-us/library/system.threading.threadpool.queueuserworkitem.aspx –

+0

@J ... Pula wątków jest przyjemna, ale sprawia, że ​​obsługa wywołania zwrotnego * z właściwego kontekstu synchronizacji * jest trudniejsza. Jednak TPL ładnie to obsługuje. –

Odpowiedz

12

Biorąc pod uwagę, że nie jesteś rzeczywiście przy znacznie funkcjonalności BackgroundWorker, polecam korzystania z OC za to w zamian:

private void DownLoadFile(string fileLocation) 
{ 
    Task.Factory.StartNew(() => Download(fileLocation)) 
     .ContinueWith(t => ReportResult(t.Result), TaskScheduler.FromCurrentSynchronizationContext()); 
} 

Powiedział, że jest przedmiotem worker nie będzie śmieci zebrane po uruchomieniu, ponieważ wątek ThreadPool sam zachowuje pracownika jako "używany obiekt". Śmieciarz nie będzie w stanie go odebrać, dopóki nie zakończy się procedura obsługi zdarzenia zakończenia, w którym to momencie nie byłoby kodu użytkownika, który mógłby osiągnąć instancję BackgroundWorker.

Ponadto prawdopodobnie zatrzyma ona instancję tej klasy w śmieciach, ponieważ zastosowane przez nią metody instancji (ReportResults) zachowują dostęp do instancji "tej" i nie kwalifikują się do GC.

+0

To nie jest tak naprawdę odpowiedź na pytanie PO. Nadal jednak dobra rada. – JDB

+1

@ Cyborgx37 Dodano bezpośrednią odpowiedź na pytanie OP. –

+0

Czy to naprawdę dobry pomysł, aby zmienna taka przestała działać? Programista, który przyjdzie po niego, spodziewa się zobaczyć odniesienie do zmiennej w zasięgu, a nie jakiejś zmiennej zombie, która jest gdzieś w eterze. –