First of all, I see that you’re confusing asymchronism with parallelism, even though the two are closely related, one is very different from the other.
When programming asynchronously, the task shall provide a feedback mechanism, normally a delegate as in the example below.
private delegate void NotificacaoIosTodos(string titulo, int posicao, int unidadeId);
public void MinhaAction()
{
var argumentos = new object[] { titulo, configuracaoItem.Posicao, unidade.UnidadeAtual };
var notificacao = new NotificacaoIosTodos(_notificacaoController.NotificacaoIosTodos, argumentos);
notificacao.BeginInvoke(new AsyncCallback(NotificacoesCallback), notificacao);
}
public void NotificacoesCallback()
{
DoSomething();
}
the example above the NotificacoesCallback
will be called as soon as the NotificacaoIosTodos
conclusion, not allocating any additional resource between the call of the MinhaAction
and NotificacoesCallback
.
Parallelism has the function of performing tasks simultaneously. One way to achieve this is to create a new Task
, remembering that you may or may not wait for the return of the same.
public void MinhaAction()
{
var notificacao = Task.Run(() => _notificacaoController.NotificacaoIosTodos(titulo, configuracaoItem.Posicao, unidade.UnidadeAtual));
notificacao.Wait();
DoSomething();
}
In the above example, a new Task
. By calling the Wait
you will be blocking the Thread
current, so it is very likely that you are allocating more resources than is necessary.
The scenario is something that should be avoided, but the conditions below can bring some gain.
Example 1
public void MinhaAction()
{
var notificacao = Task.Run(() => _notificacaoController.NotificacaoIosTodos(titulo, configuracaoItem.Posicao, unidade.UnidadeAtual));
// DoSomething1 é executado ao mesmo tempo que NotificacaoIosTodos;
DoSomething1();
// Aqui a Thread atual é bloqueada até a conclusão de NotificacaoIosTodos
notificacao.Wait();
// Por fim é executado DoSomething2
DoSomething2();
}
Example 2
public void MinhaAction()
{
var notificacoes = new Task[10];
for (var posicao = 0; posicao < notificacoes.Length; posicao++)
notificacoes[posicao] = Task.Run(() => _notificacaoController.NotificacaoIosTodos(titulo, posicao, unidade.UnidadeAtual));
// As 10 notificações serão executadas em paralelo enquanto a Thread atual é bloqueada.
Task.WaitAll(notificacoes);
// Por fim é executado DoSomething2
DoSomething();
}
Now let’s go back to asymchronism in this case using the reserved words async/await
public async Task MinhaAction()
{
await _notificacaoController.NotificacaoIosTodos(titulo, configuracaoItem.Posicao, unidade.UnidadeAtual);
DoSomething();
}
internal async Task NotificacaoIosTodos(string titulo, int posicao, int unidadeId)
{
await ConsultaBancoDeDados();
}
In the above example, a new thread will not be created. By calling NotificacaoIosTodos
it will be synchronized within the current context. This behavior is quite useful when we need to do some I/O operation, such as reading a file or consulting the database.
On the other hand, if we’re gonna do any surgery CPU Bound, then it is interesting that this process runs in a Thread separated as the Thread is released, for such we make use of the Task.Run
.
public async Task MinhaAction()
{
await Task.Run(() => _notificacaoController.NotificacaoIosTodos(titulo, configuracaoItem.Posicao, unidade.UnidadeAtual));
DoSomething();
}
internal async Task NotificacaoIosTodos(string titulo, int posicao, int unidadeId)
{
await CalcularHashCemMilVezes();
}
now a small matching example asymchronism with parallelism:
public async Task MinhaAction()
{
var notificacoes = new Task[10];
for (var posicao = 0; posicao < notificacoes.Length; posicao++)
notificacoes[posicao] = _notificacaoController.NotificacaoIosTodos(titulo, posicao, unidade.UnidadeAtual);
// As 10 notificações serão executadas em paralello enquanto a Thread atual é bloqueada.
await Task.WhenAll(notificacoes);
// Por fim é executado DoSomething2
DoSomething();
}
internal async Task NotificacaoIosTodos(string titulo, int posicao, int unidadeId)
{
await ConsultaBancoDeDados();
}
And as for the async void
, avoid using it unless the method is a method fire and Forget, as a evento
or a method that its completion is not expected by another method (such as an email sending).
And finally, despite the Task.Run
do not make execution asynchronous, it is possible to use the method ContinueWith
to add a return mechanism to the Task
.
public async Task MinhaAction()
{
var notificacao = await Task.Run(() => _notificacaoController.NotificacaoIosTodos(titulo, configuracaoItem.Posicao, unidade.UnidadeAtual));
notificacao.ContinueWith(task => {
// task.Result possui o retorno de NotificacaoIosTodos
DoSomething(task.Result);
}, TaskContinuationOptions.OnlyOnRanToCompletion);
notificacao.ContinueWith(task => {
LogarErro(task.Exception.Message);
}, TaskContinuationOptions.OnlyOnFaulted);
}
internal async Task<bool> NotificacaoIosTodos(string titulo, int posicao, int unidadeId)
{
return await ConsultaBancoDeDados();
}
Yes, the way it’s being used(through
Task.Run()
) it will be executed asynchronously. Regarding the use ofasync
andawait
see this reply– ramaral
I had read a little about the async and await, the problem is in this case the same as mine that I don’t know if I would need the async or if the Task.run ()) would make it asynchronous even calling a method that is not marked as async, I will read the answer soon, thank you very much for the tip.
– William Cézar
What makes the execution of the method
NotificacaoIosTodos()
asynchronous is the use ofTask.Run()
. The purpose ofawait
is to facilitate the "integration/interaction" of asynchronous code (Task’s) with synchronous code, allowing the code to maintain a structure similar to synchronous code.async
is necessary if you want to useawait
in a method.– ramaral
I edited the question based on the @ramaral comment that is right to say that what makes the method execution
NotificacaoIosTodos()
asynchronous is the use ofTask.Run()
. I put the documentation link that proves that his comment is correct.– George Wurthmann
@Georgewurthmann for years MS misused the word
asynchronous
in its documentation, because it used it when it wanted to sayexecutar uma thread em background
.– Tobias Mesquita
@Tobiasmesquita then the documentation is wrong to say that the work will be run asynchronously? Will it be just in a thread? I changed the answer after I saw it in the documentation.
– George Wurthmann
@Georgewurthmann take a look at this article: Task.Run Etiquette Examples you will understand a little better the functioning of
Task.Run
.– Tobias Mesquita