Wpf Desktop Api длительность вызова больше, чем фактическое время отклика API около 8-10 секунд - PullRequest
0 голосов
/ 31 января 2020

Вот случай: у меня есть приложение wpf примерно на 80 клиентах, и они общаются по одному. net api framework для обработки данных. У меня есть секундомер для отслеживания продолжительности отслеживания приложений Wpf и API. Примеры кода:

Мой атрибут API:

public class DurationControlLoggerAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var controller = actionContext.ActionDescriptor.ControllerDescriptor.ControllerName;
        var action = actionContext.ActionDescriptor.ActionName;

        actionContext.ActionArguments.Add("_stopwatch_", Stopwatch.StartNew());
    }

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        if (ConfigurationManager.AppSettings["ApiLogger"].ToLower().Trim() != "true")
            return;

        var controller = actionExecutedContext.ActionContext.ActionDescriptor.ControllerDescriptor.ControllerName;
        var action = actionExecutedContext.ActionContext.ActionDescriptor.ActionName;

        var stopWatch = (Stopwatch)actionExecutedContext.ActionContext.ActionArguments["_stopwatch_"];

        stopWatch.Stop();

        var scope = actionExecutedContext.ActionContext.Request.GetDependencyScope();
        var commonService = (ICommonService)scope.GetService(typeof(ICommonService));
        commonService.InsertLog(new Model.Common.LogModel
        {
            InsertDate = DateTime.Now.ToString(),
            LogLevel = "API",
            MachineName = "API",
            Message = $"Controller : {controller} - Action : {action} - TotalSeconds : {stopWatch.Elapsed.TotalSeconds}",
            StackTrace = string.Empty
        });
    }
}

Пример действия:

    [HttpPost]
    [DurationControlLogger]
    public bool InsertProduct(ProductModel model)
    {
        return _mainService.TracingService.InsertProduct(model);
    }

Продолжительность этого действия составляет около 0,03 секунды. С другой стороны, длительность вызова wpf api составляет около 10 секунд. Ниже приведены блоки кода Wpf:

            var Stopwatch = Stopwatch.StartNew();
            var isSuccess = DataHelper.InsertProduct(Product);
            Stopwatch.Stop();
            if (Stopwatch.Elapsed.TotalSeconds > 2)
                DataHelper.InsertTraceLog($"ProducrtBusiness - InsertProduct TotalSecond : {Stopwatch.Elapsed.TotalSeconds}");

DataHelper.InsertProduct Метод выполняет базовый c HTTP пост-запрос. Код здесь:

public static class HttpClientHelper
{
    public static T Post<T>(object model, string url)
    {
        var resultStatus = false;
        T resultData = default(T);

        using (var client = new HttpClient())
        {

            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));


            var content = new StringContent(JsonConvert.SerializeObject(model), Encoding.UTF8, "application/json");

            HttpResponseMessage response = client.PostAsync(url, content).Result;

            if (response.IsSuccessStatusCode)
            {
                string data = response.Content.ReadAsStringAsync().Result;
                var result = JsonConvert.DeserializeObject<T>(data);
                resultStatus = response.StatusCode == System.Net.HttpStatusCode.OK;
                resultData = result;
            }
        }
        return resultStatus ? resultData : default(T);
    }
    .....

Кто-нибудь имеет представление об этой ситуации?

РЕДАКТИРОВАТЬ

Я добавляю последний код журнала. Вот код: `var stopwatch = Stopwatch.StartNew ();

            HttpResponseMessage response = client.PostAsync(url, content).Result;

            stopwatch.Stop();
            if (stopwatch.Elapsed.TotalSeconds > 2)
            {
                AppendToFile($"{DateTime.Now.ToString()} - {model.ToString()} - {stopwatch.Elapsed.TotalSeconds} - Content: {jsonData}");
            }

`

Продолжительность этого журнала иногда составляет 8-10 сек c.

Ответы [ 2 ]

0 голосов
/ 11 февраля 2020

Я изменил свой метод записи класса HttpClientHelper следующим образом:

public static async Task<T> PostAsync<T>(object model, string url)
    {
        var resultStatus = false;
        T resultData = default(T);

        using (var client = new HttpClient(
                new HttpClientHandler()
                {
                    UseProxy = false
                }
            ))
        {

            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            var jsonData = JsonConvert.SerializeObject(model);
            var content = new StringContent(jsonData, Encoding.UTF8, "application/json");

            var stopwatch = Stopwatch.StartNew();

            HttpResponseMessage response = await client.PostAsync(url, content);

            stopwatch.Stop();
            if (stopwatch.Elapsed.TotalSeconds > 2)
            {
                AppendToFile($"{DateTime.Now.ToString()} - {model.ToString()} - {stopwatch.Elapsed.TotalSeconds} - Content: {jsonData}");
            }

            if (response.IsSuccessStatusCode)
            {
                string data = await response.Content.ReadAsStringAsync();
                var result = JsonConvert.DeserializeObject<T>(data);
                resultStatus = response.StatusCode == System.Net.HttpStatusCode.OK;
                resultData = result;
            }
        }
        return resultStatus ? resultData : default(T);
    }

client.PostAsyn c () метод должен выполнить asyn c для моей проблемы. Я думаю, что это связано с некоторыми проблемами управления потоками. Но этот код работает для меня сейчас.

0 голосов
/ 31 января 2020

Ну, вполне вероятно (из того, что я видел), что вы запускаете этот код на главном насосе сообщений (поток пользовательского интерфейса). Во время этого вызова метода вы выполняете асинхронный вызов (PostAsyn c) и вызываете «Result» - чтобы он работал синхронно. Однако, пока ваш поток пользовательского интерфейса ожидал, некоторые другие сообщения (обновления пользовательского интерфейса?) Были поставлены в очередь в потоке сообщений и были обработаны перед вашим вызовом для завершения секундомера (более высокий уровень DispatcherPriority?) - задерживая завершение таймера. Это чисто предположение, но я бы порекомендовал вам использовать асинхронный / ожидающий в вашем асинхронном коде и попытаться выполнить эти задачи доступа к данным в отдельном потоке

...