1

我们团队的其他成员和我创建了一个 Silverlight 应用程序。我们一直在使用 .NET 4.0。尽管我们已经将 async/await 模式放入了我们的应用程序(Microsoft.CompilerServices.AsyncTargetingPack.Net4)。

既然 MS 不会在 Silverlight 上投入太多额外的精力,我们只是想,我们构建了一个小的 HTML5/JS 应用程序——只是为了试验问题。

所以...我尝试引导应用程序,就像我们在之前的 SL 应用程序中所做的那样。我正在使用在我们的主应用程序中使用的类库来提供所有数据。为了填充上下文中的所有字典,我们调用一些异步方法来从数据库中检索数据。我也想在 MVC 应用程序中使用这个库,但是我不能调用那些异步方法,因为Application_Start在 Global.asax 中不是异步的。

如何做到这一点?

交替库不是一个可行的解决方案,因为它用于生产代码。编写一个新的库也不是一个解决方案,因为我们真的希望尽可能少地维护。

有什么建议么?

4

1 回答 1

3

我建议您在 中启动异步加载Application_Start,然后await在您的 MVC 操作中完成它。

您可以通过将 保存Task<Dictionary<..>>到静态变量然后对其进行每个异步操作来轻松完成此操作await

// Or in a repository or whatever...
public static class SharedData
{
  public static Task<Dictionary<int, string>> MyDictionary;
}

...

Application_Start(..)
{
  // Start the dictionary filling, but don't wait for it to complete.
  // Note that we're saving the Task, not await'ing it.
  MyDictionary = MyLibrary.GetDictionary();
}

然后在每个需要它的异步操作中:

public async Task<ActionResult> Get()
{
  // Asynchronously wait for the dictionary to load if it hasn't already.
  var dict = await SharedData.MyDictionary;
  ...
  return View();
}

或者,您可以为此使用异步延迟初始化。异步延迟初始化由 Stephen Toub首次公开;我在我的博客上记录了代码并将其升级到 .NET 4.5 ,并且最近将它添加到了我的AsyncEx 库中。

使用AsyncLazy<T>,您的代码将如下所示:

// Or in a repository or whatever...
public static class SharedData
{
  public static AsyncLazy<Dictionary<int, string>> MyDictionary =
      new AsyncLazy<Dictionary<int, string>>(async () =>
      {
        var ret = new Dictionary<int, string>();
        await MyLibrary.FillDictionary(ret);
        return ret;
      });
}

然后在每个需要它的异步操作中:

public async Task<ActionResult> Get()
{
  // Asynchronously wait for the dictionary to load if it hasn't already.
  var dict = await SharedData.MyDictionary;
  ...
  return View();
}

异步延迟初始化具有延迟的能力因此需要特定字典的第一个操作将await它。如果有未使用的字典,则永远不会加载它们。

于 2012-10-16T18:50:26.417 回答