Charlie Andrews Ответов: 1

Как мне это сделать асинхронное программирование в веб-API внутри foreach в .Объем 4.5


Привет ,
Я пытаюсь создать asp.net веб-api. Этот API будет вызываться из планировщика из облака один раз в 15 минут, где этот API будет искать в БД и вызывать внешний сторонний веб-сервис несколько раз с разными параметрами.Внешняя служба просто вернет true из false.

Я довольно новичок в асинхронном программировании. Я даже не знаю, что я делаю правильно , и если да, то правильно ли это делать. Я прочитал много статей и прошел через несколько одинаковых вопросов о переполнении стека, но не смог найти ответа.

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

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

public void FindSessionAndInitiateCall()
       {
           using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
           {
               using (SqlCommand cmd = new SqlCommand())
               {
                   cmd.CommandType = CommandType.StoredProcedure;
                   cmd.CommandText = "sp_FindSessionsToConnect";
                   SqlDataReader dr = cmd.ExecuteReader();
                   while (dr.Read())
                   {
                       CreateRequest(dr["ManagerMob"].ToString(), dr["EmployeeMob"].ToString(), dr["SessionDuration"].ToString(), dr["SlotId"].ToString());
                   }
               }
           }
       }

       private async Task<string> CreateRequest( string ManagerMob,string EmployeeMob, string SessionDuration, string SlotId)
       {
           HttpWebRequest request;
           var result = "";
           try
           {
               string URL = "*******************";
               request = (HttpWebRequest)WebRequest.Create(URL);
               request.Method = "POST";
               WebResponse response = await request.GetResponseAsync();
               //HttpWebResponse response = (HttpWebResponse)request.GetResponse();
               using (StreamReader reader = new StreamReader(response.GetResponseStream()))
               {
                   var objText = reader.ReadToEnd();
                   var root = JObject.Parse(objText);
                   result = root["msg"].ToString();
               }
               response.Close();
               return result;
           }
           catch (Exception ex)
           {
               return ex.Message;
           }


       }

1 Ответов

Рейтинг:
0

Richard Deeming

Вы создаете серию Task объекты, но никогда не дожидаясь их завершения. Вызывающий метод вернется до завершения работы. И если какая-либо из задач потерпит неудачу, это может привести к тому, что весь ваш процесс будет уничтожен с ошибкой "ненаблюдаемое исключение".

Вы должны сделать FindSessionAndInitiateCall метод async, и пусть он вернет a Task Затем вы сможете дождаться завершения всех дочерних задач, а вызывающий абонент сможет дождаться завершения работы.

Возможно, Вам также будет проще использовать HttpClient[^] класс вместо сырого WebRequest класс; HttpClient был разработан, чтобы быть async- дружественный с самого начала, тогда как задача-возвращающие методы на WebRequest были добавлены задолго до его создания.

Ваш код также должен установить свойство соединения команды и открыть соединение, прежде чем пытаться выполнить команду.

public async Task FindSessionAndInitiateCall(CancellationToken cancellationToken = default(CancellationToken))
{
    List<Task> tasks = new List<Task>();
    
    using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
    using (SqlCommand cmd = new SqlCommand("sp_FindSessionsToConnect", con))
    {
        cmd.CommandType = CommandType.StoredProcedure;
        
        con.Open();
        using (SqlDataReader dr = cmd.ExecuteReader())
        {
            while (dr.Read())
            {
                Task<string> request = CreateRequest(
                    dr.Field<string>("ManagerMob"), 
                    dr.Field<string>("EmployeeMob"), 
                    dr.Field<string>("SessionDuration"), 
                    dr.Field<string>("SlotId"),
                    cancellationToken);
                
                tasks.Add(request);
            }
        }
    }
    
    // Wait for all requests to complete:
    await Task.WhenAll(tasks).ConfigureAwait(false);
}


// Avoid creating new instances of the HttpClient where possible.
// See: http://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/
private static readonly HttpClient Http = new HttpClient();

private async Task<string> CreateRequest(string ManagerMob, string EmployeeMob, string SessionDuration, string SlotId, CancellationToken cancellationToken)
{
    const string URL = "*******************";
    
    var parameters = new Dictionary<string, string>
    {
        ["ManagerMob"] = ManagerMob,
        ["EmployeeMob"] = EmployeeMob,
        ["SessionDuration"] = SessionDuration,
        ["SlotId"] = SlotId,
    };
    
    var content = new FormUrlEncodedContent(parameters);
    
    var response = await Http.PostAsync(URL, content, cancellationToken);
    if (!response.IsSuccessStatusCode)
    {
        return string.Format("{0}: {1}", response.StatusCode, response.ReasonPhrase);
    }
    
    string objText = await response.Content.ReadAsStringAsync(cancellationToken);
    var root = JObject.Parse(objText);
    return root["msg"].ToString();
}

Вы неправильно используете HttpClient и это дестабилизирует ваше программное обеспечение | ASP.NET монстры[^]


Charlie Andrews

Спасибо Ричард :) Чтение статей . Это было очень полезно