Member 13390764 Ответов: 1

Задача поддержки асинхронных контроллеров о том, как реализовать классы для "спортсервиса" с помощью TAP


Проверяя результат, я знаю, что если вызовы службы выполняются асинхронно (параллельно), то общее время отклика составит чуть более 8000 миллисекунд,
Теперь мой вопрос заключается в классе для "WeatherService", как реализовать, 1 Думаю, я также использую EAP для решения этой проблемы,но теперь TAP-это рекомендуемый подход к асинхронному программированию в .NET Framework,как я могу достичь с помощью TAP
удар - это мой исходный код

1: синхронная ситуация
О контроллере
public class DefaultController : Controller
    {
        // GET: Default
        public ActionResult IndexSynchronous(string city)
        {
           System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
            watch.Start();
            NewsService newsService = new NewsService();
            string[] headlines = newsService.GetHeadlines();
            SportsService sportsService = new SportsService();
            string[] scores = sportsService.GetScores();
            WeatherService weatherService = new WeatherService();
            string[] forecast = weatherService.GetForecast();
            watch.Stop();
            TimeSpan timeSpan = watch.Elapsed;
            return Content(timeSpan.ToString());
        }
    }

О КЛАССЕ ОБСЛУЖИВАНИЯ
public class NewsService
    {     
        public string[] GetHeadlines()
        {
            Thread.Sleep(8000);
            string[] strs = { "关于赵薇的童年", "关于王宝强的童年" };
            return strs;
        }
    }
 public class SportsService
    {
        public string[] GetScores()
        {
            Thread.Sleep(8000);
            string[] strs = { "第一名分数为11", "第二名分数为22" };
            return strs;
        }
    }
 public class WeatherService
    { 
       public string[] GetForecast()
        {
            Thread.Sleep(8000);
            string[] strs = { "关于赵薇的童年", "关于王宝强的童年" };
            return strs;
        }
    }

URL: http: / / localhost: 51424 / Default/IndexSynchronous
Результат: 00:00:24.0008085
В следующем примере показана асинхронная версия метода действия индекса новостного портала.
2: асинхронная ситуация
О AsyncController
public class DefaultController : AsyncController
   {
               System.Diagnostics.Stopwatch watch = new     System.Diagnostics.Stopwatch();
       public void IndexAsync(string city)
       {
           watch.Start();
           AsyncManager.OutstandingOperations.Increment(3);
           NewsService newsService = new NewsService();
           newsService.GetHeadlinesCompleted += (sender, e) =>
           {
               AsyncManager.Parameters["headlines"] = e.strs;
               AsyncManager.OutstandingOperations.Decrement();
           };
           newsService.GetHeadlinesAsync();

           SportsService sportsService = new SportsService();
           sportsService.GetScoresCompleted += (sender, e) =>
           {
               AsyncManager.Parameters["scores"] = e.strs;
               AsyncManager.OutstandingOperations.Decrement();
           };
           sportsService.GetScoresAsync();

           WeatherService weatherService = new WeatherService();
           weatherService.GetForecastCompleted += (sender, e) =>
           {
               AsyncManager.Parameters["forecast"] = e.strs;
               AsyncManager.OutstandingOperations.Decrement();
           };
           weatherService.GetForecastAsync();

       }

       public ActionResult IndexCompleted(string[] headlines, string[] scores, string[] forecast)
       {
           string stsHeadlines = "";
           for (int i = 0; i < headlines.Length; i++)
           {
               stsHeadlines += headlines[i];
           }
           string stsScores = "";
           for (int i = 0; i < scores.Length; i++)
           {
               stsScores += scores[i];
           }
           string stsForecast = "";
           for (int i = 0; i < forecast.Length; i++)
           {
               stsForecast += forecast[i];
           }
           watch.Stop();
           TimeSpan timeSpan = watch.Elapsed;
           return Content(timeSpan.ToString() + stsHeadlines + stsScores + stsForecast);

       }

О КЛАССЕ ОБСЛУЖИВАНИЯ
public class NewsService
    {
        public string[] strs;
        public delegate void GetHeadlinesCompletedEventHandler(object Sender, GetHeadlinesCompletedEventArgs e);
        public event GetHeadlinesCompletedEventHandler GetHeadlinesCompleted;
        public class GetHeadlinesCompletedEventArgs :EventArgs
        {
            public readonly string[] strs;
            public GetHeadlinesCompletedEventArgs(string[] strs)
            {
                this.strs = strs;
            }
        }
        protected virtual void OnGetHeadlinesCompleted(GetHeadlinesCompletedEventArgs e)
        {
            if (GetHeadlinesCompleted != null)
            {  
                GetHeadlinesCompleted(this, e);   
            }
        } 
        public async void  GetHeadlinesAsync()
        {
            string[] result = await GetValueAsync();
           GetHeadlinesCompletedEventArgs e = new GetHeadlinesCompletedEventArgs(result);
           OnGetHeadlinesCompleted(e);
        }
        public Task<string[]> GetValueAsync( )
        {
            return Task.Run(() =>
            {
                Thread.Sleep(8000);
                string[] strss = { "关于赵薇的童年", "关于王宝强的童年" };
                return strss;
            });
        }
    }

  public class SportsService
    {
        public string[] strs;
        public delegate void GetScoresCompletedEventHandler(object Sender, GetScoresCompletedEventArgs e);
        public event GetScoresCompletedEventHandler GetScoresCompleted;
        public class GetScoresCompletedEventArgs : EventArgs
        {
            public readonly string[] strs;
            public GetScoresCompletedEventArgs(string[] strs)
            {
                this.strs = strs;
            }
        }
        protected virtual void OnGetScoresCompleted(GetScoresCompletedEventArgs e)
        {
            if (GetScoresCompleted != null)
            { 
                GetScoresCompleted(this, e);   
            }
        }
        public async void GetScoresAsync()
        {
            string[] result = await GetValueAsync();
            GetScoresCompletedEventArgs e = new GetScoresCompletedEventArgs(result);
            OnGetScoresCompleted(e);
        }
        public Task<string[]> GetValueAsync()
        {
            return Task.Run(() =>
            {
                Thread.Sleep(8000);
                string[] strs = { "第一名分数为11", "第二名分数为22" };
                return strs;
            });
        }
    }

 public class WeatherService
    {
        public string[] strs;
        public delegate void GetForecastCompletedEventHandler(object Sender, GetForecastCompletedEventArgs e);
        public event GetForecastCompletedEventHandler     GetForecastCompleted;
        public class GetForecastCompletedEventArgs : EventArgs
        {
            public readonly string[] strs;
            public GetForecastCompletedEventArgs(string[] strs)
            {
                this.strs = strs;
            }
        }
        protected virtual void OnGetForecastCompleted(GetForecastCompletedEventArgs e)
        {
            if (GetForecastCompleted != null)
            {  
                GetForecastCompleted(this, e);   
            }
        } 
        public async void GetForecastAsync()
        {
            string[] result = await GetValueAsync();
            GetForecastCompletedEventArgs e = new GetForecastCompletedEventArgs(result);
            OnGetForecastCompleted(e);
        }
        public Task<string[]> GetValueAsync()
        {
            return Task.Run(() =>
            {
                Thread.Sleep(8000);
                string[] strs = { "关于赵薇的童年", "关于王宝强的童年" };
                return strs;
            });
        }

    }

URL: http: / / localhost: 51424 / Default/Index
РЕЗУЛЬТАТ:
00:00:08.0519411


Что я уже пробовал:

var newsService = new NewsService();
  var sportsService = new SportsService();

  return View("Common",
      new PortalViewModel {
      NewsHeadlines = await newsService.GetHeadlinesAsync(),
      SportsScores = await sportsService.GetScoresAsync()
  });

Nathan Minier

Не очень ясно, где ваш процесс ломается. Пожалуйста, добавьте больше контекста, например, что вы пытаетесь сделать и почему это не работает.

Member 13390764

ладно, извини

Member 13390764

помогите мне, спасибо

1 Ответов

Рейтинг:
5

Richard Deeming

Когда вы используете await, остальная часть метода не выполняется до тех пор, пока задача, которую вы ждете, не будет завершена. Если эта задача занимает 8 секунд, следующая задача не начнется, по крайней мере, через 8 секунд.

Вам нужно начать все три задания сразу, а затем дождаться их завершения.

public async Task<ActionResult> IndexAsync(string city)
{
    var watch = System.Diagnostics.Stopwatch.StartNew();
    
    // Start all three tasks:
    
    var newsService = new NewsService();
    var newsTask = newsService.GetHeadlinesAsync(); // NB: No "await" here
    
    var sportsService = new SportsService();
    var sportsTask = sportsService.GetScoresAsync(); // Or here
    
    var weatherService = new WeatherService();
    var weatherTask = weatherService.GetForecastAsync(); // Or here
    
    // Wait for all three tasks to finish:
    await Task.WhenAll(newsTask, sportsTask, weatherTask);
    
    // Get the results:
    string[] headlines = await newsTask;
    string[] scores = await sportsTask;
    string[] forecast = await weatherTask;
    
    watch.Stop();
    
    TimeSpan timeSpan = watch.Elapsed;
    return Content(timeSpan.ToString());
}

NB: Это было бы намного проще в использовании async и await чтобы сделать ваши тестовые службы асинхронными:
public class NewsService
{     
    public async Task<string[]> GetHeadlinesAsync()
    {
        await Task.Delay(8000);
        string[] strs = { "...", "..." };
        return strs;
    }
}

Кроме того, Класс AsyncController[^] предоставляется только для обратной совместимости с MVC 3. Предполагая, что вы используете v4 или более позднюю версию, это больше не требуется. Вы можете просто сделать так, чтобы ваши действия возвращали Task<T> вместо.