Я написал библиотеку C #, в которой есть метод для подсчета слов из нескольких проходов текста параллельно. Отрывки текста задаются в виде символьных потоков, где при каждом вызове getnextchar()
происходит случайная задержка. Мой библиотечный метод должен взять массив этих символьных потоков и вернуть комбинированный подсчет частоты слов. Для этого у меня есть безопасная общая структура данных с частотой слов и поток для чтения каждого потока символов и обновления общей коллекции. Когда все потоки завершены, я возвращаю структуру данных клиентскому приложению.
Клиентскому приложению требуются промежуточные результаты комбинированного подсчета слов каждые 10 секунд. Для этого я использую делегата для повторного вызова клиента каждые 10 секунд с результатами до тех пор, пока все рабочие потоки не будут завершены, после чего я возвращаю окончательные результаты клиенту.
Моя проблема заключается в том, что при обратном вызове клиента с промежуточными результатами мне приходится блокировать свою общую структуру данных и ждать, пока клиентское приложение вернется из обратного вызова, прежде чем я смогу разблокировать ее. Пока выполняется обратный вызов, все рабочие потоки блокируются в ожидании блокировки структуры данных. Это не похоже на разумную вещь, потому что я не думаю, что должен полагаться или доверять клиентскому коду, чтобы он возвращался быстро или даже вообще. Тем не менее, они могут думать только о том, что делать это, не полагаясь на код клиента, - это сделать копию или снимок моей структуры данных и передать ее клиенту через обратный вызов. Это происходит за счет памяти и вычислений, но после создания копии рабочие могут продолжить обновление общей коллекции, а обратный вызов может делать все, что захочет.
У меня вопрос в два раза:
1) Это меньшее из двух зол, допускающее возможность плохой реализации обратного вызова клиента для блокировки работников или периодического выполнения дорогостоящей операции.
2) Есть ли способ решить эту проблему, который не делает ни один из вышеперечисленных?