#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 вы можете выполнить одно ожидание, пока все дескрипторы будут просигнализированы.