TaskScheduler - это низкоуровневая абстракция, предназначенная для постановки задачи в очередь исполнения на потоках.
SynchronizationContext - это специальная абстракция, которая предназначена для того, чтобы определить, как будет исполняться задача, и, что более важно, определить, как будет происходить коммуникация между потоками, в рамках исполнения данной задачи.
Говоря простым языком, когда нужно (имеет смысл для десктопных приложений, у которых есть основной поток, исполняющий UI, графический интерфейс), synchronization context запомнит ваше окружение - поток, точку вызова, выполнит асинхронную операцию на другом потоке и продолжит исполнение результатов в заполненном потоке.
Для каждого контекста может быть определен планировщик задач, который и будет выполнять задачи, а контекст будет управлять их исполнением ("переключать" между потоками, грубо говоря - если это требуется).
Не для всех фреймворков нужно такое поведение, для веб нет контекста синхронизации и нам в конечном итоге без разницы, на каких потоках будет исполнен наш код.
Но, для winforms / wpf это очень важный механизм, так как любое взаимодействие с интерфейсом возможно только из потока UI.