AFAIK, tudo o que sabe é que, em algum momento, seu SetResult
ou SetException
método está sendo chamado para concluir o Task<T>
exposto por meio de sua Task
propriedade.
Em outras palavras, ele atua como produtor de uma Task<TResult>
e sua conclusão.
Eu vi aqui o exemplo:
Se eu precisar de uma maneira de executar um Func de forma assíncrona e ter uma tarefa para representar essa operação.
public static Task<T> RunAsync<T>(Func<T> function)
{
if (function == null) throw new ArgumentNullException(“function”);
var tcs = new TaskCompletionSource<T>();
ThreadPool.QueueUserWorkItem(_ =>
{
try
{
T result = function();
tcs.SetResult(result);
}
catch(Exception exc) { tcs.SetException(exc); }
});
return tcs.Task;
}
Que poderia ser usado * se eu não tinha Task.Factory.StartNew
- Mas eu não tenho Task.Factory.StartNew
.
Questão:
Alguém pode explicar por exemplo um cenário relacionado diretamente ao TaskCompletionSource
e não a uma hipotética situação em que eu não tenho Task.Factory.StartNew
?
c#
.net
.net-4.0
task-parallel-library
taskcompletionsource
Royi Namir
fonte
fonte
Respostas:
Uso-o principalmente quando apenas uma API baseada em eventos está disponível ( por exemplo, soquetes do Windows Phone 8 ):
Portanto, é especialmente útil quando usado junto com a
async
palavra-chave C # 5 .fonte
SomeApiWrapper
se espera em algum lugar, até que o editor levante o evento que faz com que essa tarefa seja concluída?Microsoft.Bcl.Async
pacote no NuGet, que permite asasync/await
palavras - chave em projetos .NET 4.0 (recomenda-se o VS2012 e superior).Em minhas experiências,
TaskCompletionSource
é ótimo para agrupar antigos padrões assíncronos noasync/await
padrão moderno .O exemplo mais benéfico em que consigo pensar é quando trabalho
Socket
. Ele possui os antigos padrões APM e EAP, mas não osawaitable Task
métodos que possuemTcpListener
eTcpClient
possuem.Pessoalmente, tenho vários problemas com a
NetworkStream
turma e prefiro o cruSocket
. Como também amo oasync/await
padrão, criei uma classe de extensãoSocketExtender
que cria vários métodos de extensãoSocket
.Todos esses métodos são usados
TaskCompletionSource<T>
para agrupar as chamadas assíncronas da seguinte maneira:I passar a
socket
nosBeginAccept
métodos para que eu recebo um ligeiro aumento de desempenho fora do compilador não ter que içar o parâmetro local.Então a beleza de tudo:
fonte
Begin.. End...
instruções.Para mim, um cenário clássico para o uso
TaskCompletionSource
é quando é possível que meu método não precise necessariamente fazer uma operação demorada. O que isso nos permite fazer é escolher os casos específicos em que gostaríamos de usar um novo thread.Um bom exemplo disso é quando você usa um cache. Você pode ter um
GetResourceAsync
método que procure no cache o recurso solicitado e retorne imediatamente (sem usar um novo encadeamento, usandoTaskCompletionSource
) se o recurso foi encontrado. Somente se o recurso não for encontrado, gostaríamos de usar um novo thread e recuperá-lo usandoTask.Run()
.Um exemplo de código pode ser visto aqui: Como executar um código condicionalmente de forma assíncrona usando tarefas
fonte
Task.FromResult
para fazer isso. Obviamente, se você estiver usando o 4.0 e não tiver um para oTask.FromResult
qual você usaria um TCS, escreva o seuFromResult
.Task.FromResult
está disponível apenas desde o .NET 4.5. Antes disso, era assim que se conseguia esse comportamento.Task.Run
, indicando que é 4,5+. E meu comentário anterior abordou especificamente o .NET 4.0.Em este post , Levi Botelho descreve como usar a
TaskCompletionSource
escrever um invólucro assíncrona para um processo de tal forma que você pode lançá-lo e aguardar a sua rescisão.e seu uso
fonte
Parece que ninguém foi mencionado, mas acho que os testes de unidade também podem ser considerados suficientes na vida real .
Acho
TaskCompletionSource
útil quando zombando de uma dependência com um método assíncrono.No programa real em teste:
Nos testes de unidade:
Afinal, esse uso do TaskCompletionSource parece outro caso de "um objeto Task que não executa código".
fonte
TaskCompletionSource é usado para criar objetos de tarefas que não executam código. Em cenários do mundo real, TaskCompletionSource é ideal para operações vinculadas de E / S. Dessa forma, você obtém todos os benefícios das tarefas (por exemplo, valores de retorno, continuações etc.) sem bloquear um encadeamento durante a operação. Se sua "função" for uma operação vinculada a E / S, não é recomendável bloquear um encadeamento usando uma nova tarefa . Em vez disso, usando TaskCompletionSource , você pode criar uma tarefa escrava para indicar apenas quando sua operação de ligação de E / S termina ou falha.
fonte
Há um exemplo do mundo real com uma explicação decente nesta postagem do blog "Parallel Programming with .NET" . Você realmente deveria lê-lo, mas aqui está um resumo de qualquer maneira.
A postagem do blog mostra duas implementações para:
A primeira implementação mostrada é baseada
Task<>
e possui duas falhas principais. O segundo post de implementação continua a atenuá-los usandoTaskCompletionSource<>
.Aqui está a segunda implementação:
fonte
await Task.Delay(millisecondsDelay); action(); return;
ou (em .Net 4.0)return Task.Delay(millisecondsDelay).ContinueWith( _ => action() );
Isso pode simplificar demais as coisas, mas a fonte TaskCompletion permite aguardar um evento. Como o tcs.SetResult é definido apenas quando o evento ocorre, o chamador pode aguardar a tarefa.
Assista a este vídeo para obter mais informações:
http://channel9.msdn.com/Series/Three-Essential-Tips-for-Async/Lucian03-TipsForAsyncThreadsAndDatabinding
fonte
O cenário do mundo real em que usei
TaskCompletionSource
é ao implementar uma fila de downloads. No meu caso, se o usuário iniciar 100 downloads, não quero acioná-los todos de uma vez e, em vez de retornar uma tarefa estratificada, retornarei uma tarefa anexada aTaskCompletionSource
. Depois que o download é concluído, o encadeamento que está funcionando, a fila conclui a tarefa.O principal conceito aqui é que estou me desacoplando quando um cliente solicita que uma tarefa seja iniciada a partir de quando ela realmente é iniciada. Nesse caso, porque não quero que o cliente precise lidar com o gerenciamento de recursos.
observe que você pode usar async / waitit no .net 4, desde que esteja usando um compilador C # 5 (VS 2012+), veja aqui para obter mais detalhes.
fonte
Eu costumava
TaskCompletionSource
executar uma tarefa até que ela fosse cancelada. Nesse caso, é um assinante do ServiceBus que normalmente quero executar enquanto o aplicativo for executado.fonte
TaskCompletionSource
é para Tarefas comoWaitHandle
é para Thread. E assim podemos usarTaskCompletionSource
para executar sinalização precisa .Um exemplo é a minha resposta a esta pergunta: Atraso no ContentDialog após clicar em OK
fonte