Мне очень нравится находить путь к самому потоку монитора (тот, который активирован .BeginInvoke), чтобы генерировать исключение в главном потоке.
За исключением чего-то другого подобно ThreadAbortException
, отсутствует механизм для вставки исключения в другой произвольный поток.
Если вы собираетесь использовать метод делегата BeginInvoke()
и хотите перехватить исключение в потоке, отличном от того, где сам делегат вызывается, тогда вам нужно будет вызвать EndInvoke()
в этом потоке.
Другим вариантом будет явное и ручное обращение с исключением. Т.е. перехватить исключение с помощью try
/ catch
в рабочем потоке, а затем использовать явно определенный механизм по вашему выбору (например, ConcurrentQueue<T>
) для передачи перехваченного исключения в код, выполняющийся в основном потоке.
Все это говорит о том, что использование метода BeginInvoke()
делегата никогда не было таким идеальным способом выполнения кода асинхронно, как сейчас, и сегодня это даже хуже идеи. Из вашего вопроса не ясно, какова природа «основного потока», не говоря уже о том, имеет ли этот поток контекст синхронизации. Но если предположить, что это так (например, это поток GUI или контекст ASP. NET и т. Д. c.), То желаемое поведение легко реализуется с помощью Task.Run()
для запуска асинхронной операции, а затем с помощью await
в главном потоке, чтобы зафиксировать завершение этой операции, вместе с любым сгенерированным исключением.
В этом отношении, даже если ваш основной поток в настоящее время не имеет контекста синхронизации, это может быть правильный подход - дать ему один. Либо используя один из существующих механизмов, либо написав свой собственный. Это было бы хорошей идеей, если, например, вы ожидаете, что в коде часто встречается сценарий «распространение исключения из рабочего потока в основной поток» в коде. Это позволит вам использовать встроенную языковую поддержку для решения этой проблемы (т. Е. async
/ await
), вместо того, чтобы использовать что-то для каждого экземпляра. Реализация контекста синхронизации не тривиальна, но это работа, которую вы можете выполнить один раз, а затем снова и снова использовать.