【问题标题】:Is my method running asynchronously? [closed]我的方法是异步运行的吗? [关闭]
【发布时间】:2014-06-07 17:33:54
【问题描述】:

在我的游戏中,我注意到有些卡顿,因为AdComponent 试图从互联网上下载一个新广告以绘制在我的游戏上。

冻结功能如何初始化:

// Declarations
DrawableAd drawableAd;

// Inside constructor of my game class
AdComponent.Initialize("MyAppId");
Rectangle rect = new Rectangle(0, resolution_h_ - 50, 320, 50);
drawableAd_ = AdComponent.Current.CreateAd("AdId", rect, false); // false is to set AutoRefresh of the ad

要使广告可点击并下载,我必须在每个更新步骤中调用:AdComponent.Current.Update(e_.ElapsedTime);

DrawableAd infos

问题是,如果我同步调用它,它会使我的游戏在下载新广告时冻结一段时间:

private void OnUpdate(object sender, GameTimerEventArgs e)
{
     // ... GameUpdates
     AdComponent.Current.Update(e.ElapsedTime); 
}

所以,我认为解决方案是将AdComponent.Current.Update(e.ElapsedTime); 放在后台线程上,以“低优先级”来解决冻结问题。所以我做到了:

  private async void UpdateAds()
  {
      if (ad_update_completed_)
          await Task.Factory.StartNew(() => UpdateAdsMethod());
  }

  private async Task UpdateAdsMethod()
  {
      ad_update_completed_ = false;
      AdComponent.Current.Update(e_.ElapsedTime);
      ad_update_completed_ = true;
  }

  private void OnUpdate(object sender, GameTimerEventArgs e)
  {
     // ... GameUpdates
     e_ = e;
     UpdateAds();
  }

在此之后,我注意到(没有使用分析器)大部分冻结(不是全部)都消失了。但我有一些疑问,因为编译器发出警告说UpdateAdsMethod(); 将被同步执行。

我做错了什么?

【问题讨论】:

  • 异步 != 多线程。没有足够的信息来帮助优化您的代码。
  • @Aron 我可以添加哪些信息?
  • 当然是从分析器得到的结果。
  • 您的问题范围之外的一些cmets:1)不要使用async void(事件处理程序除外),如果它不返回任何结果,请使用async Task。 2) 你没有理由使用Task.Factory.StartNew。只需await UpdateAdsMethod
  • @Aron "async != multithreading" 在 asyncTask 领域是

标签: c# silverlight asynchronous xna task


【解决方案1】:

AdComponent.Current.Update() 不会返回 Task,因此您的 UpdateAdsMethod 可以简化(见下文)。由于您在子任务中调用 UpdateAdsMethod(),因此无需让它返回另一个任务。它应该简单地读作如下:

    private void UpdateAdsMethod()
    {
        ad_update_completed_ = false;
        AdComponent.Current.Update(e_.ElapsedTime);
        ad_update_completed_ = true;
    }

这应该消除编译器警告。请记住,如果在任何方法中使用 await 关键字,则使用 await 的方法的签名必须在方法声明中包含 async。请参阅下面的 UpdateAds()

您的方法肯定在后台运行,因为调用是在子任务中(您在 UpdateAds() 期间创建了它。

编辑:所以您的代码现在应该类似于:

private async Task UpdateAds()
    {
        if (ad_update_completed_)
            await Task.Factory.StartNew(() => UpdateAdsMethod());
    }

    private void UpdateAdsMethod()
    {
        ad_update_completed_ = false;
        AdComponent.Current.Update(e_.ElapsedTime);
        ad_update_completed_ = true;
    }

欲了解更多信息,请访问http://msdn.microsoft.com/en-us/magazine/jj991977.aspx

【讨论】:

  • 你同意 Daniel Mann 的评论吗?我应该删除StartNew吗?
  • @misiMe 不确定他在#2 中的意思。这样做会导致许多“考虑将'await'运算符应用于调用结果”编译器警告
  • 我不敢相信我有多么不同意你。 UpdateAdsMethod() 看起来是线程不安全的。如果public void UpdateAdsMethod 抛出你无法捕捉到它,你的整个应用程序将停止运行。您应该返回一个任务,然后将其包装在 Try Catch 中。最后,“DrawableAdComponent”这个名称表明需要 UI 线程。
  • @Aron 现在你只是在拖钓。走开
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多