Pergunta

Eu estou usando o padrão Model-View-Presenter em um WinForms projeto e um problema (entre muitos) que eu estou tendo é quando o formulário diz o apresentador para fazer alguma coisa e, em seguida, é un-reativa, enquanto o apresentador vai da faça. Felizmente no meu projeto eu não tenho nenhum problema com fazer todas as chamadas do apresentador assíncrona a questão é exatamente como fazê-lo?

deve cada chamada apresentador apenas ser envolto em uma nova criação de thread? *

new Thread(()=>_presenter.DoSomething()).Start();

O que são as melhores práticas aqui? E se o usuário pressiona uma "Abortar o que está fazendo" botão? Como faço para abortar graciosamente?

. * Realisticamente eu provavelmente só usar algum tipo de um proxy no apresentador de fazer isso em vez de colocar a criação thread no WinForm

Foi útil?

Solução

Eu só posso dizer que eu pensei sobre isso (antes de ler sua pergunta;). Primeiro eu rig os lugares onde isso realmente importa; por exemplo, o acesso chokepoint DB. Se há um lugar que não deve ser executado no contexto "UI" (você pode salvá-lo de http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.current.aspx no segmento interface do usuário e então comparar mais tarde para não-UI contexto de sincronização), em seguida, Debug.BitchAndMoan () sobre ele. Quaisquer cálculos mais longos (que "deve" ser tudo claramente separados em suas próprias variedades, certo;). Deve afirmar que

Eu acho que você deve pelo menos fazer o tipo de execução da função apresentador configurável através atributo que é então obedecida por proxy. (Apenas no caso de você querer algo feito de forma serial).

O cancelamento de uma tarefa é realmente problema do apresentador, mas você deve ter um objeto de referência que diz o que você quer parar. Se você seguir o caminho proxy, então você poderia pegar tópicos criados na tarefa lista com IAsyncResult de, mas ainda é um problema para decidir qual é suposto ser cancelada se mesma ação é permitida a ser chamado várias vezes em paralelo. Portanto, você deve fornecer a tarefa com um nome específico-call adequado quando você iniciá-lo; o que implica de forma demasiada lógica em vista lateral -.> Apresentador provavelmente deve pedir Vista para pedir utilizador que uma das tarefas devem ser eliminados

A minha experiência é que isso geralmente é apenas contornado usando eventos (estilo SCSF). Se fazê-lo a partir do zero, eu iria a maneira procuração desde SCSF tem sido uma dor de tantas maneiras que eu duvido sanidade de seus designers.

Outras dicas

Eu costumo colocar qualquer ação que pode (realisticamente) demorar mais de um segundo ou dois em uma tarefa separada, algo como:

public interface ITask
{
    void ExecuteTask (ITaskExecutionContext context);
    void AfterSuccess(ITaskExecutionContext context);
    void AfterFailure(ITaskExecutionContext context);
    void AfterAbortion(ITaskExecutionContext context);
}

Eu também tenho uma abstração para a execução de tais tarefas:

public interface ITaskExecutor : IDisposable
{
    void BeginTask(ITask task);
    void TellTaskToStop();
}

Uma das implementações deste ITaskExecutor está usando o BackgroundWorker:

public class BackgroundTaskExecutor : ITaskExecutor
{
    public void BeginTask(ITask task)
    {
        this.task = task;
        worker = new BackgroundWorker ();
        worker.DoWork += WorkerDoWork;
        worker.RunWorkerCompleted += WorkerRunWorkerCompleted;
        worker.WorkerSupportsCancellation = true;

        worker.RunWorkerAsync();
    }

    ...
}

I dependem fortemente da injeção de dependência e COI coisas fios juntos. No apresentador então eu apenas chamar algo como:

GoAndDontReturnUntilYouBringMeALotOfMoneyTask task = new GoAndDontReturnUntilYouBringMeALotOfMoneyTask(parameters);
taskExecutor.BeginTask(task);

Cancelar / abort botões são, então, conectado de forma que eles dizem o executor de tarefas / tarefa para abortar.

Na verdade, é um pouco mais complexa do que os apresentados aqui, mas esta é a ideia geral.

Por que não fazer o padrão de proxy que você usar aceitar um par de retornos de chamada para retornar os resultados ou abortar?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top