← Back to list

C# SynchronizationContext — O Guia Definitivo para Domar a Thread de UI [2025 Edition]

Aprenda como usar SynchronizationContext para criar ViewModels multiplataforma em WPF, UWP e WinUI sem acoplamento, garantindo código…

Diogocmr · 2025-11-18 12:29 · 51 claps · 3.6 min read
#c-sharp-programming #wpf #uwp #winui #threading
Open on Medium ↗
Wiki topics: CRY · Crypto & Web3 SEO · SEO & SEM 💻 · Programming 📚 · Books & Reading

C# SynchronizationContext — O Guia Definitivo para Domar a Thread de UI [2025 Edition]

Aprenda como usar SynchronizationContext para criar ViewModels multiplataforma em WPF, UWP e WinUI sem acoplamento, garantindo código limpo, testável e seguro para a UI.

Introdução — O Problema do Código Compartilhado no Desktop

Desenvolver aplicações desktop modernas em C# pode ser um trabalho árduo — especialmente quando você tenta compartilhar ViewModels entre WPF, UWP e WinUI 3. Embora todas as plataformas usem XAML, cada uma possui sua própria maneira de lidar com a thread da UI, e isso complica bastante quando você quer manter ViewModels limpos, desacoplados e multiplataforma.

E aqui está a raiz do problema:

Se você tentar atualizar propriedades de UI a partir de tarefas assíncronas, timers ou callbacks, rapidamente encontrará erros como:

The calling thread cannot access this object because a different thread owns it.

A solução “ingênua” é fazer gambiarra:

#if WPF
    Application.Current.Dispatcher.Invoke(() => { ... });
#elif UWP
    await CoreApplication.MainView.Dispatcher.RunAsync(...);
#elif WINUI
    DispatcherQueue.TryEnqueue(() => { ... });
#endif

× Isso é feio, frágil e totalmente oposto ao MVVM. × Faz seus ViewModels dependerem da plataforma. × Quebra testes unitários. × É impossível de escalar.

Mas existe uma solução elegante, antiga e ainda extremamente poderosa no .NET:

SynchronizationContext — A Abstração Perfeita para a Thread de UI

O C# SynchronizationContext é a maneira mais simples e limpa de enviar código de volta para a UI sem depender da plataforma. Ele funciona porque cada tecnologia de UI define seu próprio contexto:

  • WPF define o DispatcherSynchronizationContext
  • UWP define o SynchronizationContext próprio da CoreWindow
  • WinUI 3 define um DispatcherQueueSynchronizationContext

Quando você está na UI Thread, SynchronizationContext.Current aponta exatamente para o contexto da UI daquela plataforma.

Ou seja:

Uma única APIFunciona em todas as plataformas .NET desktopSeu ViewModel continua 100% agnóstico da UI

Capturando o SynchronizationContext na Inicialização do ViewModel

A melhor prática é capturar o contexto no construtor do ViewModel, quando ele é instanciado pela View na UI Thread.

public abstract class BaseViewModel
{
    protected readonly SynchronizationContext _uiContext;

    protected BaseViewModel()
    {
        _uiContext = SynchronizationContext.Current 
                     ?? new SynchronizationContext();
    }
}

Essa única linha garante que você agora possui uma ponte segura para a UI, independente da tecnologia usada.

Executando Código na UI com Post()

Suponha que seu ViewModel baixa dados em background e depois precisa atualizar a UI:

public async Task LoadDataAsync()
{
    await Task.Run(() =>
    {
        Thread.Sleep(1000);
        var data = "Dados carregados!";

        _uiContext.Post(_ =>
        {
            Status = data;
            Items.Add(data);

        }, null);
    });
}

Por que usar .Post?

  • Ele é assíncrono
  • Não bloqueia a thread que chamou
  • É perfeito para atualizações de UI

Já o .Send() executa de forma síncrona e deve ser evitado na maioria dos cenários de UI.

Mas e o async/await? Ele não resolve isso sozinho?

Sim — na maioria das vezes.

Quando você faz isso:

public async Task LoadAsync()
{
    IsBusy = true;

    var result = await Api.GetAsync();

    // De volta à UI Thread!
    Data = result;
    IsBusy = false;
}

Isso funciona porque:

✔ O await captura o SynchronizationContext atual ✔ E retorna para ele quando a task termina

Mas isso só acontece se:

  • o método começou na UI Thread, e
  • você não usou ConfigureAwait(false)

Quando o SynchronizationContext é indispensável

Existem cenários em que o callback não volta para a UI sozinho:

Task.Run() — Sempre executa no thread pool, nunca na UI.

System.Timers.Timer — Executa em threads arbitrárias.

FileSystemWatcher — Depende de IO Completion Threads.

Bibliotecas Externas Que não sabem nada sobre sua UI.

Em todos esses casos, você precisa usar .Post() para retornar à UI.

Benefícios Reais na Arquitetura

Ao usar C# SynchronizationContext, você ganha:

  • ViewModels verdadeiramente agnósticos: Sem Dispatcher, CoreDispatcher, nem DispatcherQueue.
  • Código multiplataforma real: Um único ViewModel funciona em WPF, UWP e WinUI.
  • Testes unitários simples: Sem dependências de UI.
  • Redução de acoplamento: Maior clareza arquitetural e manutenção mais fácil.

Perguntas Frequentes sobre C# SynchronizationContext

1. O SynchronizationContext funciona também no MAUI?

Sim, mas o MAUI usa seu próprio dispatcher. O SynchronizationContext funciona, mas em alguns casos o MainThread do MAUI é mais apropriado.

2. Posso usar Send()?

Pode, mas raramente é recomendado. Ele bloqueia a thread chamadora e pode causar deadlocks facilmente.

3. O contexto pode ser nulo?

Sim — fora da UI Thread. Por isso usamos o fallback: SynchronizationContext.Current ?? new SynchronizationContext()

4. Isso é melhor do que usar Dispatcher diretamente?

Sim, porque remove a dependência da plataforma e mantém o ViewModel limpo.

5. O SynchronizationContext é rápido?

Sim. O overhead é mínimo, e ele delega o trabalho para os mecanismos nativos de cada UI.

6. Funciona no .NET 8?

Perfeitamente. O comportamento permanece estável desde o .NET Framework 2.0.

Conclusão

O SynchronizationContext é, sem dúvida, uma das ferramentas mais subestimadas do .NET moderno. Ele resolve um dos maiores desafios no desenvolvimento desktop: manter ViewModels realmente multiplataforma sem depender de componentes específicos como Dispatcher, CoreDispatcher ou DispatcherQueue. Ao usar essa abstração, você elimina acoplamentos desnecessários, simplifica sua arquitetura e garante um código muito mais limpo, testável e fácil de manter.

Se você trabalha com WPF, UWP ou WinUI — ou se simplesmente quer ViewModels mais robustos — aprender a usar o SynchronizationContext é essencial.


메타데이터
post_id
b2139cc6eb84
slug
c-synchronizationcontext-o-guia-definitivo-para-domar-a-thread-de-ui-2025-edition-b2139cc6eb84
url
https://medium.com/@diogocmr2002/c-synchronizationcontext-o-guia-definitivo-para-domar-a-thread-de-ui-2025-edition-b2139cc6eb84
canonical_url
https://medium.com/@diogocmr2002/c-synchronizationcontext-o-guia-definitivo-para-domar-a-thread-de-ui-2025-edition-b2139cc6eb84
author_url
https://medium.com/@diogocmr2002
status
ok
fetched_at
2026-07-15 19:33:18