how do you implement Async Operations in C# and MVVM?

后端 未结 3 1119
甜味超标
甜味超标 2021-02-04 14:28

hi what is the easiest way to implement asynch operations on WPF and MVVM, lets say if user if user hits enter when on a field i want to launch a command and then return back wh

相关标签:
3条回答
  • 2021-02-04 14:52

    How about a BackgroundWorker instance to call your command on the VM ?

    Update: Scratch the above suggestion.. There's an online video on MVVM by Jason Dolinger.. I recommend you take a look at that. It's a cleaner way where the view is thin/ does not hold any threading code.

    To summarize:

    • the VM ctor caches the Dispatcher.CurrentDispatcher object (main thread).
    • when updating the backing store (results), use _dispatcher.BeginInvoke( () => _results.AddRange( entries) ) so that the UI is updated correctly.
    0 讨论(0)
  • 2021-02-04 14:54

    Rob Eisenberg showed a really clean implementation of running async operations in MVVM during his MIX10 talk. He has posted the source code on his blog.

    The basic idea is that you implement the command as returning an IEnumerable and use the yield keyword to return the results. Here is a snippet of code from his talk, which does a search as a background task:

        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();
        }
    

    Hope that helps.

    0 讨论(0)
  • 2021-02-04 15:07

    In Shawn Wildermuth's MSDN Article he did something like this: check out the article here: http://msdn.microsoft.com/en-us/magazine/dd458800.aspx

    and his more recent blog post here: 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;
    }
    

    with an implementation like this:

    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;
        }
      }
    }
    
    0 讨论(0)
提交回复
热议问题