C#在等待之前返回 - 无需启动新任务

时间:2015-08-03 09:17:16

标签: c# .net xamarin.ios async-await

这是针对用iOS编写的Xamarin应用。我的所有应用程序代码都在主线程中运行(即UI thread)。

UI代码执行如下操作:

public async void ButtonClicked()
{
    StartSpinner();
    var data = await UpdateData();
    StopSpinner();
    UpdateScreen(data);
}

UpdateData函数执行如下操作:

public Task<Data> UpdateData()
{
   var data = await FetchFromServer();
   TriggerCacheUpdate();
   return data;
}

TriggerCacheUpdate最终调用下面定义的以下函数

public Task RefreshCache()
{
    var data = await FetchMoreDataFromServer();
    UpdateInternalDataStructures();
}

我的问题是如何编写TriggerCacheUpdate?要求是:

  1. 不能异步,我不想要UpdateData因此 ButtonClicked等待RefreshCache之前完成 仍在进行中。
  2. UpdateInternalDataStructures需要在主(UI)线程上执行,即上面显示的所有其他代码都执行的线程。
  3. 以下是我提出的一些备选方案:

    public void TriggerCacheUpdate()
    {
        RefreshCache();
    }
    

    以上工作但会生成编译器警告。此外,RefreshCache的异常处理无效。

    public void TriggerCacheUpdate()
    {
        Task.Run(async() =>
        {
            await RefreshCache();
        });
    }
    

    上述内容违反了要求2,因为UpdateInternalDataStructures未在与其他所有内容相同的线程上执行。

    我认为可行的替代方案是:

    private event EventHandler Done; 
    public void TriggerCacheUpdate()
    {
        this.task = RefreshCache();
        Done += async(sender, e) => await this.task;
    }
    
    Task RefreshCache() {
        var data = await FetchMoreDataFromServer();
        UpdateInternalDataStructures();
        if (Done != null) {
           Done(this, EventArgs.Empty);
        }
    }
    

    以上是否有效?到目前为止,我还没有遇到过有限的测试问题。是否有更好的方法来撰写TriggerCacheUpdate

2 个答案:

答案 0 :(得分:0)

很难说没有能够测试它,但看起来你的触发缓存更新方法很好,这是你的RefreshCache需要改变。在RefreshCache中,您没有在UI线程中等待“data”的结果返回,因此将ConfigureAwait设置为false。

public async Task RefreshCache()
{
    var data = await FetchMoreDataFromServer().ConfigureAwait(false);
    UpdateInternalDataStructures();
}

答案 1 :(得分:0)

您的事件处理程序是异步的。这意味着,即使您等待任务完成,您的UI仍然保持响应。因此,即使您要等待TriggerCacheUpdate返回,您的UI仍将保持响应。

但是,如果您确定自己对TriggerCachUpdate的结果不感兴趣,那么您可以在不等待的情况下启动任务:

public Task<Data> UpdateData()
{
    var data = await FetchFromServer();
    Task.Run( () => TriggerCacheUpdate());
    return data;
}
  

注意:注意:您不知道TriggerCachUpdate何时完成,即使它成功结束或引发异常也不知道。另外:检查如果在前一个任务尚未完成的情况下启动新的TriggerCacheUpdate任务会发生什么。

对于想要使用Task.Factory.StartNew的用户,请参阅MSDN中有关它的讨论:

Task.Run vs Task.Factory.StartNew