C # Асинхронная работа внутри BackgroundWorker? - PullRequest
2 голосов
/ 11 ноября 2011

Я не лучший в многопоточности, и это немного сложно, так что, надеюсь, я смогу объяснить это хорошо.

По сути, у меня есть задача BackgroundWorker, и внутри нее есть несколько вызовов для получения информации с веб-сайта.Возможно, есть лучший способ сделать это, но я не могу придумать один.Я делаю это потому, что хочу иметь одно событие, когда все обращений к сайту (и последующая обработка информации) завершены.

Это в основном то, что я имею в виду:

private void loadContent() {
    BackgroundWorker worker = new BackgroundWorker();
    worker.DoWork += delegate(object sender, DoWorkEventArgs e) {
        getAndProcessInformation(desiredInformationName);
        getAndProcessInformation(someOtherDesiredInformationName);
    };
    worker.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e) {
        MessageBox.Show("Finished!");
        Dispatcher.BeginInvoke(() => { progressBar(false); });
    };
    worker.RunWorkerAsync();
}
private void getAndProcessInformation(string theInformationIWant){
    Fetcher dataFetcher = new Fetcher(); //Fetcher is a custom class that reads information from a web server
    dataFetch.receivedData += delegate(DataResponseArgs args) {
        //Process some data
    };
    dataFetch.requestData(theInformationIWant);
}

Итак, получается, что RunWorkerCompleted вызывается сразу после двух getAndProcessInformation методы вызываются, и до того, как данные действительно закончат обработку.Можно ли каким-то образом заставить RunWorkerCompleted запускаться только после того, как обработка в методах будет фактически завершена?

Теперь я вижу, что BackgroundWorker на самом деле не нужен, поскольку обработка фактически уже выполняется в отдельном потоке, но я не знаю альтернативы, которая позволила бы мне получить желаемый результатзапуск одного события после завершения всей обработки.Итак, я думаю, это действительно два вопроса;Должен ли я продолжать использовать BackgroundWorker, и, если да, как я могу это исправить, или, если нет, какова альтернатива?

1 Ответ

1 голос
/ 11 ноября 2011

Если ваш сборщик уже создает свой собственный поток, использование BackgroundWorker не имеет особого смысла, как вы уже поняли.

Поскольку вы еще не поделились реализацией Fetcher. Вероятно, должно быть что-то вроде этого, если вы хотите придерживаться того, что у вас уже есть

private void getAndProcessInformation(string theInformationIWant){
    Fetcher dataFetcher = new Fetcher(); 
    var eventHandle =  new ManualResetEvent(false);
    dataFetch.receivedData += delegate(DataResponseArgs args) {
        //Process some data
        eventHandle.Set();
    };
    dataFetch.requestData(theInformationIWant);
    eventHandle.WaitOne();
}

Таким образом, функция getAndProcessInformation не вернется, пока не будет выполнена обработка. Только один Fetch будет работать одновременно.

Если вы хотите, чтобы все сборщики данных работали параллельно, вы должны удалить WaitOne и заставить getAndProcessInformation возвращать дескриптор ожидания. Затем в DoWork вы можете сделать одно ожидание, чтобы все сигналы были переданы.

...