温馨提示:本文翻译自stackoverflow.com,查看原文请点击:c# - Wpf Desktop Api call duration more longer than actual api response time about 8-10 seconds
api c# duration request wpf

c# - WPF Desktop Api调用持续时间比实际的API响应时间长约8-10秒

发布于 2020-03-29 21:35:20

这是一个例子:我在大约80个客户端上有wpf应用程序,它们为数据处理传递单个.net框架api。我有一些秒表跟踪器,用于跟踪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方法执行基本的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秒。

查看更多

提问者
Aydin Ayaydin
被浏览
107
Dean Chalk 2020-02-01 02:34

好吧,很可能(从我所看到的)您正在主消息泵(UI线程)上运行此代码。在此方法调用期间,您将执行异步调用(PostAsync)并调用'Result'-使它同步运行。但是,当您的UI线程正在等待时,其他一些消息(UI更新?)在消息泵上排队,并在您调用结束秒表(更高的DispatcherPriority?)之前被处理-延迟计时器结束。这纯粹是推测,但我建议您在异步代码中使用一些async / await,并尝试在单独的线程上执行这些数据访问任务