Calling an asynchronous and synchronous method

Asked

Viewed 5,321 times

2

I have a synchronous method, in it I call another method of another controller which would have to be executed asynchronous.

I call this other method this way:

Task.Run(() => _notificacaoController.NotificacaoIosTodos(titulo,
configuracaoItem.Posicao,unidade.UnidadeAtual));

This is my method:

  internal void NotificacaoIosTodos(string titulo, int posicao, int unidadeId)
    {
        try
        {
            var unidade = _contexto.Unidade.FirstOrDefault(l => l.UnidadeId == unidadeId);
            var pessoas = _contexto.PessoaUnidade.Include(l => l.Pessoa)
                .Where(l => l.Pessoa.Dispositivo == (int)enumDispositivo.Ios && l.UnidadeId == unidadeId)
                .ToList();
            foreach (PessoaUnidade pessoa in pessoas)
            {
                Notificacao notificacao = new Notificacao {Posicao = posicao};
                _contexto.Notificacao.Add(notificacao);
                _contexto.SaveChanges();
                PessoaNotificacao pessoaNotificacao = new PessoaNotificacao
                {
                    Visualizado = false,
                    PessoaUnidade = pessoa,
                    Notificacao = notificacao
                };
                _contexto.PessoaNotificacao.Add(pessoaNotificacao);
                _contexto.SaveChanges();
            }

            Push.EnviarTodos(unidade.OneSignalAuth, unidade.OneSignalId, titulo, posicao, unidade.Nome);
        }
        catch (Exception)
        {
            throw;
        }
    }

I put the whole method, but my doubt is whether the method is working asynchronously or synchronously, the method NotificacaoIosTodos should be marked with async and usingawait?

That way he’s now he’s already running on another thread asynchronously?

  • 1

    Yes, the way it’s being used(through Task.Run()) it will be executed asynchronously. Regarding the use of async and await see this reply

  • 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.

  • 2

    What makes the execution of the method NotificacaoIosTodos() asynchronous is the use of Task.Run(). The purpose of await 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 use await in a method.

  • 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 of Task.Run(). I put the documentation link that proves that his comment is correct.

  • @Georgewurthmann for years MS misused the word asynchronous in its documentation, because it used it when it wanted to say executar uma thread em background.

  • @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.

  • 1

    @Georgewurthmann take a look at this article: Task.Run Etiquette Examples you will understand a little better the functioning of Task.Run.

Show 2 more comments

2 answers

7


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();
}
  • Thanks for the reply, clarified me a lot . I was really confusing Asynchronism with parallelism!! Thank you very much.

1

I put the whole method but my doubt and about synchronicity of this method, the Notified method should be marked with async and usandoawait ?

Whether to use it as asynchronous or synchronous to choice is yours.

That way he’s now he’s already running on another thread of shape asincrona ?

Yes, the method is running asynchronously. Also, it runs in a Thread.

But, on the contrary, an asynchronous call does not necessarily create a new Thread.

To use as async you will need to change it as in the example below:

internal void async NotificacaoIosTodos(string titulo, int posicao, int unidadeId)
{
  ...
}

And on the call use await, example:

await Task.Run(() => _notificacaoController.NotificacaoIosTodos(titulo,
configuracaoItem.Posicao, unidade.UnidadeAtual));

However the Task Run. already makes the work asynchronous.

  • My intention is to execute it accordingly, I doubt how to use the await in this case, I would use it when calling the method ? await Task.run type(() => ??

  • That’s exactly what @Williamcézar said. I’ll improve on that answer as soon as I have time for you to better understand the use in this case with Task.run.

  • Ok, another question is what am I calling this method from a normal method, in case when I try to use the await it will ask to mark this method with async tbm right ? in case the two would have to be marked as async?

  • Thank you so much for the patience in intender my question, it helped a lot.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.