代码之家  ›  专栏  ›  技术社区  ›  Oscar Cabrero

如何在C和MVVM中实现异步操作?

  •  9
  • Oscar Cabrero  · 技术社区  · 15 年前

    嗨,在wpf和mvvm上实现异步操作最简单的方法是什么?假设用户在我想启动命令的字段上点击enter,然后返回,而线程将执行一些搜索操作,然后返回并更新属性,以便通知可以更新绑定。

    谢谢!

    3 回复  |  直到 13 年前
        1
  •  3
  •   Gishu    15 年前

    A怎么样 BackgroundWorker 在虚拟机上调用命令的实例?

    更新: 擦掉上面的建议。Jason Dolinger在MVVM上有一个在线视频。我建议你看看那个。如果视图很薄/不包含任何线程代码,这是一种更干净的方法。

    总结:

    • vm ctor缓存Dispatcher.CurrentDispatcher对象(主线程)。
    • 更新备份存储(结果)时,请使用 _dispatcher.BeginInvoke( () => _results.AddRange( entries) ) 以便正确更新UI。
        2
  •  8
  •   jan    13 年前

    RobEisenberg展示了在MVVM中运行异步操作的一个非常干净的实现。 MIX10 talk . 他已经在他的博客上发布了源代码。

    基本思想是,将该命令实现为返回IEnumerable,并使用yield关键字返回结果。下面是他演讲中的一段代码,作为后台任务进行搜索:

        public IEnumerable<IResult> ExecuteSearch()
        {
            var search = new SearchGames
            {
                SearchText = SearchText
            }.AsResult();
    
            yield return Show.Busy();
            yield return search;
    
            var resultCount = search.Response.Count();
    
            if (resultCount == 0)
                SearchResults = _noResults.WithTitle(SearchText);
            else if (resultCount == 1 && search.Response.First().Title == SearchText)
            {
                var getGame = new GetGame
                {
                    Id = search.Response.First().Id
                }.AsResult();
    
                yield return getGame;
                yield return Show.Screen<ExploreGameViewModel>()
                    .Configured(x => x.WithGame(getGame.Response));
            }
            else SearchResults = _results.With(search.Response);
    
            yield return Show.NotBusy();
        }
    

    希望有帮助。

        3
  •  0
  •   silverfighter    15 年前

    在肖恩·威尔德茅斯的《MSDN》一文中,他这样做了: 在这里查看文章: http://msdn.microsoft.com/en-us/magazine/dd458800.aspx

    他最近在这里发表的博客: http://wildermuth.com/2009/12/15/Architecting_Silverlight_4_with_RIA_Services_MEF_and_MVVM_-_Part_1

    public interface IGameCatalog
    {
      void GetGames();
      void GetGamesByGenre(string genre);
      void SaveChanges();
    
      event EventHandler<GameLoadingEventArgs> GameLoadingComplete;
      event EventHandler<GameCatalogErrorEventArgs> GameLoadingError;
      event EventHandler GameSavingComplete;
      event EventHandler<GameCatalogErrorEventArgs> GameSavingError;
    }
    

    使用这样的实现:

    public class GameCatalog : IGameCatalog
    {
      Uri theServiceRoot;
      GamesEntities theEntities;
      const int MAX_RESULTS = 50;
    
      public GameCatalog() : this(new Uri("/Games.svc", UriKind.Relative))
      {
      }
    
      public GameCatalog(Uri serviceRoot)
      {
        theServiceRoot = serviceRoot;
      }
    
      public event EventHandler<GameLoadingEventArgs> GameLoadingComplete;
      public event EventHandler<GameCatalogErrorEventArgs> GameLoadingError;
      public event EventHandler GameSavingComplete;
      public event EventHandler<GameCatalogErrorEventArgs> GameSavingError;
    
      public void GetGames()
      {
        // Get all the games ordered by release date
        var qry = (from g in Entities.Games
                   orderby g.ReleaseDate descending
                   select g).Take(MAX_RESULTS) as DataServiceQuery<Game>;
    
        ExecuteGameQuery(qry);
      }
    
      public void GetGamesByGenre(string genre)
      {
        // Get all the games ordered by release date
        var qry = (from g in Entities.Games
                   where g.Genre.ToLower() == genre.ToLower()
                   orderby g.ReleaseDate
                   select g).Take(MAX_RESULTS) as DataServiceQuery<Game>;
    
        ExecuteGameQuery(qry);
      }
    
      public void SaveChanges()
      {
        // Save Not Yet Implemented
        throw new NotImplementedException();
      }
    
      // Call the query asynchronously and add the results to the collection
      void ExecuteGameQuery(DataServiceQuery<Game> qry)
      {
        // Execute the query
        qry.BeginExecute(new AsyncCallback(a =>
        {
          try
          {
            IEnumerable<Game> results = qry.EndExecute(a);
    
            if (GameLoadingComplete != null)
            {
              GameLoadingComplete(this, new GameLoadingEventArgs(results));
            }
          }
          catch (Exception ex)
          {
            if (GameLoadingError != null)
            {
              GameLoadingError(this, new GameCatalogErrorEventArgs(ex));
            }
          }
    
        }), null);
      }
    
      GamesEntities Entities
      {
        get
        {
          if (theEntities == null)
          {
            theEntities = new GamesEntities(theServiceRoot);
          }
          return theEntities;
        }
      }
    }
    
    推荐文章