Асинхронная работа C # в фоновом режиме?

#c# #multithreading #asynchronous #backgroundworker

#c# #многопоточность #асинхронный #фоновый редактор

Вопрос:

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

По сути, у меня есть задача 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 вызывается сразу после вызова двух методов GET и Processinformation и до фактического завершения обработки данных. Есть ли какой-либо способ заставить RunWorkerCompleted запускаться только после того, как обработка в методах фактически завершена?

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

Ответ №1:

Если ваш Fetcher уже создает свой собственный поток, использование 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 не вернется, пока не будет выполнена обработка. Одновременно будет выполняться только одна выборка.

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