Passing an *Awaitable* Anonymous Function as a Parameter

六眼飞鱼酱① 提交于 2019-12-01 13:41:16

问题


Code first. This is what I'm trying to do. I'm close, but I think I just need to fix the way I've defined my parameter in the UpdateButton method.

private async void UpdateButton(Action<bool> post)
{
    if (!await post())
        ErrorBox.Text = "Error posting message.";
}

private void PostToTwitter()
{
    UpdateButton(async () => await new TwitterAction().Post("Hello, world!"));
}

private void PostToFacebook()
{
    UpdateButton(async () => await new FacebookAction().Post("Hello, world!"));
}

Unfortunately, the !await post() doesn't work because, "Type 'void' is not awaitable." So the question is, how do I define my parameter in this method to support an awaitable parameter?

Here's how the TwitterAction().Post() is defined...

public virtual async Task<bool> Post(string messageId){...}


回答1:


private async void UpdateButton(Func<Task<bool>> post)
{
    if (!await post())
        ErrorBox.Text = "Error posting message.";
}

--EDIT--

UpdateButton(()=>Post("ss"));

private async void UpdateButton(Func<Task<bool>> post)
{
    if (!await post())
        this.Text = "Error posting message.";
}

public virtual async Task<bool> Post(string messageId)
{
    return await Task.Factory.StartNew(() => true);
}



回答2:


You need to pass this as a Task<bool>, not an Action<bool>.

This provides something that's "awaitable".

I believe this will work, given your current code:

private async Task UpdateButtonAsync(Task<bool> post)
{
    if (!await post)
        ErrorBox.Text = "Error posting message.";
}

// This will work if Post returns Task<bool> in the current API...
private void PostToTwitter()
{
    UpdateButtonAsync(new TwitterAction().Post("Hello, world!"));
}

If you do not want to start the Task<bool> immediately, and need to keep it as passing a lambda, there is still no reason for the lambda to be async. In that case, you could use:

private async Task UpdateButtonAsync(Func<Task<bool>> post)
{
    if (!await post())
        ErrorBox.Text = "Error posting message.";
}

// This will work if Post returns Task<bool> in the current API...
private void PostToTwitter()
{
    UpdateButtonAsync(() => new TwitterAction().Post("Hello, world!"));
}

This causes the lambda to return the Task<bool> (no async/await required, as Post already returns Task<bool>), and the update method to run the lambda.

Personally, I find the first option (above) simpler, and suspect it is more likely what you want. Given your API already returns Task<T>, you can just pass that around and await it directly.



来源:https://stackoverflow.com/questions/12466049/passing-an-awaitable-anonymous-function-as-a-parameter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!