Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

362
Visualizações
How to implement synchronous Task-returning method without warning CS1998?

Take for example the following interface:

interface IOracle
{
    Task<string> GetAnswerAsync(string question);
}

Some implementations of this interface might use async/await. Others might not need to. For example, consider this simple toy implementation.

class SimpleOracle
{
    public Dictionary<string, string> Lookup { get; set; }

    // Warning CS1998: This async method lacks 'await' operators
    // and will run synchonously.
    public async Task<string> GetAnswerAsync(string question)
    {
        string answer = Lookup[question];
        return answer;
    }
}

The compiler warning CS1998 of course makes sense. The usual suggestion is to remove the async keyword and use Task.FromResult, but it misses a subtle issue. What if the code throws an exception? Then that code transform changes the behavior of the method: the async version will wrap any exception in a Task; the non-async version will not, without an explict try-catch.

Leaving the async keyword works exactly as I want, but it produces a compiler warning, and I don't think suppressing those is wise.

How should I refactor my method implementation to not produce a compiler warning while also wrapping all exceptions with Task as any other async method would?

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

The mechanical translation I use to convert from the async version that yields compiler warning CS1998 to a non-async version that behaves identically is as follows.

  • Remove the async keyword.
  • Wrap the entire existing method body with a try-catch.
  • Define a TaskCompletionSource<T> called tcs before the try-catch.
  • Replace all existing instances of return <expr>; with tcs.SetResult(<expr>); followed by return tcs.Task;.
  • Define the catch block to call tcs.SetException(e) followed by return tcs.Task;.

For example:

public Task<string> GetAnswerAsync(string question)
{
    var tcs = new TaskCompletionSource<string>();
    try
    {
        string answer = Lookup[question];
        tcs.SetResult(answer);
        return tcs.Task;
    }
    catch (Exception e)
    {
        tcs.SetException(e);
        return tcs.Task;
    }
}

This can be expressed more generally by the following, although I don't know if it would be appropriate to actually introduce such a helper method into a codebase.

public static Task<T> AsyncPattern(Func<T> func)
{
    var tcs = new TaskCompletionSource<T>();
    try
    {
        tcs.SetResult(func());
    }
    catch (Exception e)
    {
        tcs.SetException(e);
    }
    return tcs.Task;
}
over 4 years ago · Santiago Trujillo Relatório

0

If you're using .NET 4.6, you can use Task.FromException to handle the exception case, just as you use FromResult to handle the successful case:

public Task<string> GetAnswerAsync(string question)
{
    try
    {
        return Task.FromResult(Lookup[question]);
    }
    catch(Exception e)
    {
        return Task.FromException<string>(e);
    }
}

If you're using .NET 4.5 then you'll need to write your own FromException method, but it's pretty trivial:

public static Task<T> FromException<T>(Exception e)
{
    var tcs = new TaskCompletionSource<T>();
    tcs.SetException(e);
    return tcs.Task;
}
public static Task FromException(Exception e)
{
    var tcs = new TaskCompletionSource<bool>();
    tcs.SetException(e);
    return tcs.Task;
}
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda