Вы можете уведомить основной поток о прогрессе с помощью метода обратного вызова. То есть:
// in the main thread
public void ProgressCallback(int jobNumber, int status)
{
// handle notification
}
Вы можете передать этот метод обратного вызова в рабочий поток, когда вызываете его (то есть как делегат), или код рабочего потока может «неявно» знать о нем. В любом случае работает.
Параметры jobNumber и status являются лишь примерами. Возможно, вы захотите использовать другой способ определения выполняемых заданий, и вы можете использовать перечисляемый тип для статуса. Как бы вы это ни делали, имейте в виду, что ProgressCallback будет вызываться несколькими потоками одновременно, поэтому, если вы обновляете какие-либо общие структуры данных или записываете данные журнала, вам придется защищать эти ресурсы с помощью блокировок или других методов синхронизации.
Вы также можете использовать события для этого, но поддержание актуальности подписок на события основного потока может быть потенциальной проблемой. У вас также есть вероятность утечки памяти, если вы забудете отписать основной поток от событий определенного рабочего потока. Хотя события, безусловно, будут работать, я бы порекомендовал обратный вызов для этого приложения.