Stacking await keywords











up vote
-1
down vote

favorite












I am trying to reduce the boiler plate code from getting data from my cache repository. I was basically copying and pasting the same code over and over, so I put all of that logic into a new class, CacheReadCommand. I am trying to do this using async/await as my database repository has already implemented async/await. What has ended up happening is that I got this stack of await keywords when I am trying to execute CacheReadCommand.Read. This is not actually returning anything and leaving the application hung up. Where did I go wrong here?



CacheReadCommand



public class CacheReadCommand : ICacheReadCommand {
private readonly ICacheRepository _repo;

public CacheReadCommand(ICacheRepository repo) {
_repo = repo;
}

public async Task<T> Read<T>(string cacheKey, Func<T> query) {
T retVal = await _repo.GetValue<T>(cacheKey);

if(retVal == null) {
retVal = query.Invoke();

if(retVal != null) {
await _repo.SetValue<T>(cacheKey, retVal);
}
}

return retVal;
}
}


** Settings Repository **



    public async Task<Setting> GetSetting(Guid guid, string key) {
string cacheKey = $"GetSetting_{guid}_{key}";

return await await _readCommand.Read(cacheKey, async () => await ReadOne<Setting>("GetSetting", guid));
}

protected async Task<T> ReadOne<T>(string sql, Guid siteGuid) {
DynamicParameters parms = new DynamicParameters();
parms.Add(PARMNAME_GUID, siteGuid.ToFormattedString());

return await ReadOne<T>(GetCommandDefinition(sql, parms));
}









share|improve this question


















  • 1




    The await await doesn't make sense. This shouldn't compile. Can you please provide a Minimal, Complete, and Verifiable example?
    – Enigmativity
    Nov 19 at 22:09






  • 1




    @Enigmativity It makes perfect sense and compiles just fine whenever the expression following it is a Task<Task<T>> (or Task<Task>), which is the case here.
    – Servy
    Nov 19 at 22:44












  • If you want to give an async query to your Read function, you need to ask explicitly for a Func<Task<T>> and await it. Right now you're calling Invoke() on the delegate, which returns a Task<Setting> and you give it as-is to your repository. I'm fairly certain that this is not what you want
    – Kevin Gosse
    Nov 19 at 23:13












  • @Servy - Yes, but there's no double task here as far as I can see?
    – Enigmativity
    Nov 20 at 0:38










  • @KevinGosse implementing Func<Task<T>> did alleviate the second await, however I am still using query.Invoke(). I just have to await that. I have compiled it and tested it. That worked. This solution works for me, if you want to put your comment as an answer, I'll close it.
    – fizch
    Nov 20 at 0:46















up vote
-1
down vote

favorite












I am trying to reduce the boiler plate code from getting data from my cache repository. I was basically copying and pasting the same code over and over, so I put all of that logic into a new class, CacheReadCommand. I am trying to do this using async/await as my database repository has already implemented async/await. What has ended up happening is that I got this stack of await keywords when I am trying to execute CacheReadCommand.Read. This is not actually returning anything and leaving the application hung up. Where did I go wrong here?



CacheReadCommand



public class CacheReadCommand : ICacheReadCommand {
private readonly ICacheRepository _repo;

public CacheReadCommand(ICacheRepository repo) {
_repo = repo;
}

public async Task<T> Read<T>(string cacheKey, Func<T> query) {
T retVal = await _repo.GetValue<T>(cacheKey);

if(retVal == null) {
retVal = query.Invoke();

if(retVal != null) {
await _repo.SetValue<T>(cacheKey, retVal);
}
}

return retVal;
}
}


** Settings Repository **



    public async Task<Setting> GetSetting(Guid guid, string key) {
string cacheKey = $"GetSetting_{guid}_{key}";

return await await _readCommand.Read(cacheKey, async () => await ReadOne<Setting>("GetSetting", guid));
}

protected async Task<T> ReadOne<T>(string sql, Guid siteGuid) {
DynamicParameters parms = new DynamicParameters();
parms.Add(PARMNAME_GUID, siteGuid.ToFormattedString());

return await ReadOne<T>(GetCommandDefinition(sql, parms));
}









share|improve this question


















  • 1




    The await await doesn't make sense. This shouldn't compile. Can you please provide a Minimal, Complete, and Verifiable example?
    – Enigmativity
    Nov 19 at 22:09






  • 1




    @Enigmativity It makes perfect sense and compiles just fine whenever the expression following it is a Task<Task<T>> (or Task<Task>), which is the case here.
    – Servy
    Nov 19 at 22:44












  • If you want to give an async query to your Read function, you need to ask explicitly for a Func<Task<T>> and await it. Right now you're calling Invoke() on the delegate, which returns a Task<Setting> and you give it as-is to your repository. I'm fairly certain that this is not what you want
    – Kevin Gosse
    Nov 19 at 23:13












  • @Servy - Yes, but there's no double task here as far as I can see?
    – Enigmativity
    Nov 20 at 0:38










  • @KevinGosse implementing Func<Task<T>> did alleviate the second await, however I am still using query.Invoke(). I just have to await that. I have compiled it and tested it. That worked. This solution works for me, if you want to put your comment as an answer, I'll close it.
    – fizch
    Nov 20 at 0:46













up vote
-1
down vote

favorite









up vote
-1
down vote

favorite











I am trying to reduce the boiler plate code from getting data from my cache repository. I was basically copying and pasting the same code over and over, so I put all of that logic into a new class, CacheReadCommand. I am trying to do this using async/await as my database repository has already implemented async/await. What has ended up happening is that I got this stack of await keywords when I am trying to execute CacheReadCommand.Read. This is not actually returning anything and leaving the application hung up. Where did I go wrong here?



CacheReadCommand



public class CacheReadCommand : ICacheReadCommand {
private readonly ICacheRepository _repo;

public CacheReadCommand(ICacheRepository repo) {
_repo = repo;
}

public async Task<T> Read<T>(string cacheKey, Func<T> query) {
T retVal = await _repo.GetValue<T>(cacheKey);

if(retVal == null) {
retVal = query.Invoke();

if(retVal != null) {
await _repo.SetValue<T>(cacheKey, retVal);
}
}

return retVal;
}
}


** Settings Repository **



    public async Task<Setting> GetSetting(Guid guid, string key) {
string cacheKey = $"GetSetting_{guid}_{key}";

return await await _readCommand.Read(cacheKey, async () => await ReadOne<Setting>("GetSetting", guid));
}

protected async Task<T> ReadOne<T>(string sql, Guid siteGuid) {
DynamicParameters parms = new DynamicParameters();
parms.Add(PARMNAME_GUID, siteGuid.ToFormattedString());

return await ReadOne<T>(GetCommandDefinition(sql, parms));
}









share|improve this question













I am trying to reduce the boiler plate code from getting data from my cache repository. I was basically copying and pasting the same code over and over, so I put all of that logic into a new class, CacheReadCommand. I am trying to do this using async/await as my database repository has already implemented async/await. What has ended up happening is that I got this stack of await keywords when I am trying to execute CacheReadCommand.Read. This is not actually returning anything and leaving the application hung up. Where did I go wrong here?



CacheReadCommand



public class CacheReadCommand : ICacheReadCommand {
private readonly ICacheRepository _repo;

public CacheReadCommand(ICacheRepository repo) {
_repo = repo;
}

public async Task<T> Read<T>(string cacheKey, Func<T> query) {
T retVal = await _repo.GetValue<T>(cacheKey);

if(retVal == null) {
retVal = query.Invoke();

if(retVal != null) {
await _repo.SetValue<T>(cacheKey, retVal);
}
}

return retVal;
}
}


** Settings Repository **



    public async Task<Setting> GetSetting(Guid guid, string key) {
string cacheKey = $"GetSetting_{guid}_{key}";

return await await _readCommand.Read(cacheKey, async () => await ReadOne<Setting>("GetSetting", guid));
}

protected async Task<T> ReadOne<T>(string sql, Guid siteGuid) {
DynamicParameters parms = new DynamicParameters();
parms.Add(PARMNAME_GUID, siteGuid.ToFormattedString());

return await ReadOne<T>(GetCommandDefinition(sql, parms));
}






c# async-await delegates






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 19 at 21:38









fizch

1,49031936




1,49031936








  • 1




    The await await doesn't make sense. This shouldn't compile. Can you please provide a Minimal, Complete, and Verifiable example?
    – Enigmativity
    Nov 19 at 22:09






  • 1




    @Enigmativity It makes perfect sense and compiles just fine whenever the expression following it is a Task<Task<T>> (or Task<Task>), which is the case here.
    – Servy
    Nov 19 at 22:44












  • If you want to give an async query to your Read function, you need to ask explicitly for a Func<Task<T>> and await it. Right now you're calling Invoke() on the delegate, which returns a Task<Setting> and you give it as-is to your repository. I'm fairly certain that this is not what you want
    – Kevin Gosse
    Nov 19 at 23:13












  • @Servy - Yes, but there's no double task here as far as I can see?
    – Enigmativity
    Nov 20 at 0:38










  • @KevinGosse implementing Func<Task<T>> did alleviate the second await, however I am still using query.Invoke(). I just have to await that. I have compiled it and tested it. That worked. This solution works for me, if you want to put your comment as an answer, I'll close it.
    – fizch
    Nov 20 at 0:46














  • 1




    The await await doesn't make sense. This shouldn't compile. Can you please provide a Minimal, Complete, and Verifiable example?
    – Enigmativity
    Nov 19 at 22:09






  • 1




    @Enigmativity It makes perfect sense and compiles just fine whenever the expression following it is a Task<Task<T>> (or Task<Task>), which is the case here.
    – Servy
    Nov 19 at 22:44












  • If you want to give an async query to your Read function, you need to ask explicitly for a Func<Task<T>> and await it. Right now you're calling Invoke() on the delegate, which returns a Task<Setting> and you give it as-is to your repository. I'm fairly certain that this is not what you want
    – Kevin Gosse
    Nov 19 at 23:13












  • @Servy - Yes, but there's no double task here as far as I can see?
    – Enigmativity
    Nov 20 at 0:38










  • @KevinGosse implementing Func<Task<T>> did alleviate the second await, however I am still using query.Invoke(). I just have to await that. I have compiled it and tested it. That worked. This solution works for me, if you want to put your comment as an answer, I'll close it.
    – fizch
    Nov 20 at 0:46








1




1




The await await doesn't make sense. This shouldn't compile. Can you please provide a Minimal, Complete, and Verifiable example?
– Enigmativity
Nov 19 at 22:09




The await await doesn't make sense. This shouldn't compile. Can you please provide a Minimal, Complete, and Verifiable example?
– Enigmativity
Nov 19 at 22:09




1




1




@Enigmativity It makes perfect sense and compiles just fine whenever the expression following it is a Task<Task<T>> (or Task<Task>), which is the case here.
– Servy
Nov 19 at 22:44






@Enigmativity It makes perfect sense and compiles just fine whenever the expression following it is a Task<Task<T>> (or Task<Task>), which is the case here.
– Servy
Nov 19 at 22:44














If you want to give an async query to your Read function, you need to ask explicitly for a Func<Task<T>> and await it. Right now you're calling Invoke() on the delegate, which returns a Task<Setting> and you give it as-is to your repository. I'm fairly certain that this is not what you want
– Kevin Gosse
Nov 19 at 23:13






If you want to give an async query to your Read function, you need to ask explicitly for a Func<Task<T>> and await it. Right now you're calling Invoke() on the delegate, which returns a Task<Setting> and you give it as-is to your repository. I'm fairly certain that this is not what you want
– Kevin Gosse
Nov 19 at 23:13














@Servy - Yes, but there's no double task here as far as I can see?
– Enigmativity
Nov 20 at 0:38




@Servy - Yes, but there's no double task here as far as I can see?
– Enigmativity
Nov 20 at 0:38












@KevinGosse implementing Func<Task<T>> did alleviate the second await, however I am still using query.Invoke(). I just have to await that. I have compiled it and tested it. That worked. This solution works for me, if you want to put your comment as an answer, I'll close it.
– fizch
Nov 20 at 0:46




@KevinGosse implementing Func<Task<T>> did alleviate the second await, however I am still using query.Invoke(). I just have to await that. I have compiled it and tested it. That worked. This solution works for me, if you want to put your comment as an answer, I'll close it.
– fizch
Nov 20 at 0:46












1 Answer
1






active

oldest

votes

















up vote
0
down vote



accepted










If you want to give an async query to your Read function, you need to ask explicitly for a Func<Task<T>> and await it. Right now you're calling Invoke() on the delegate, which returns a Task<Setting>.



So instead you should do something like:



public async Task<T> Read<T>(string cacheKey, Func<Task<T>> query) {
T retVal = await _repo.GetValue<T>(cacheKey);

if(retVal == null) {
retVal = await query();

if(retVal != null) {
await _repo.SetValue<T>(cacheKey, retVal);
}
}

return retVal;
}





share|improve this answer





















    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53383011%2fstacking-await-keywords%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    0
    down vote



    accepted










    If you want to give an async query to your Read function, you need to ask explicitly for a Func<Task<T>> and await it. Right now you're calling Invoke() on the delegate, which returns a Task<Setting>.



    So instead you should do something like:



    public async Task<T> Read<T>(string cacheKey, Func<Task<T>> query) {
    T retVal = await _repo.GetValue<T>(cacheKey);

    if(retVal == null) {
    retVal = await query();

    if(retVal != null) {
    await _repo.SetValue<T>(cacheKey, retVal);
    }
    }

    return retVal;
    }





    share|improve this answer

























      up vote
      0
      down vote



      accepted










      If you want to give an async query to your Read function, you need to ask explicitly for a Func<Task<T>> and await it. Right now you're calling Invoke() on the delegate, which returns a Task<Setting>.



      So instead you should do something like:



      public async Task<T> Read<T>(string cacheKey, Func<Task<T>> query) {
      T retVal = await _repo.GetValue<T>(cacheKey);

      if(retVal == null) {
      retVal = await query();

      if(retVal != null) {
      await _repo.SetValue<T>(cacheKey, retVal);
      }
      }

      return retVal;
      }





      share|improve this answer























        up vote
        0
        down vote



        accepted







        up vote
        0
        down vote



        accepted






        If you want to give an async query to your Read function, you need to ask explicitly for a Func<Task<T>> and await it. Right now you're calling Invoke() on the delegate, which returns a Task<Setting>.



        So instead you should do something like:



        public async Task<T> Read<T>(string cacheKey, Func<Task<T>> query) {
        T retVal = await _repo.GetValue<T>(cacheKey);

        if(retVal == null) {
        retVal = await query();

        if(retVal != null) {
        await _repo.SetValue<T>(cacheKey, retVal);
        }
        }

        return retVal;
        }





        share|improve this answer












        If you want to give an async query to your Read function, you need to ask explicitly for a Func<Task<T>> and await it. Right now you're calling Invoke() on the delegate, which returns a Task<Setting>.



        So instead you should do something like:



        public async Task<T> Read<T>(string cacheKey, Func<Task<T>> query) {
        T retVal = await _repo.GetValue<T>(cacheKey);

        if(retVal == null) {
        retVal = await query();

        if(retVal != null) {
        await _repo.SetValue<T>(cacheKey, retVal);
        }
        }

        return retVal;
        }






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 20 at 7:11









        Kevin Gosse

        32.4k35271




        32.4k35271






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53383011%2fstacking-await-keywords%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Feedback on college project

            Futebolista

            Albești (Vaslui)