【问题标题】:Wpf Desktop Api call duration more longer than actual api response time about 8-10 secondsWpf Desktop Api 调用持续时间比实际 api 响应时间长约 8-10 秒
【发布时间】:2020-01-31 10:17:05
【问题描述】:

这里是案例: 我在大约 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 post 请求。代码在这里:

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 秒。

【问题讨论】:

  • 我会使用像 wireshark 或 fiddler 这样的嗅探器并查看以下两种方法 1) 数据是否压缩/编码 2) 你看到的是 http 1.0(流模式)还是 1.1 块模式。版本将在标头中 3)检查请求和响应之间的时间以确定延迟是在客户端还是在服务器上。
  • 感谢@jdwend 的建议。我在客户端机器上安装了 wireshark 来跟踪网络流量(ps:fiddler 由于政策原因没有工作)。我检查了所有数据流量,每个请求持续时间都在 1 秒以下。但我仍然有 8-10 秒的日志.. 客户端机器中的问题。
  • 日志文件有多大。日志文件的附加似乎需要很长时间。驱动器上剩余多少空间?您使用的是什么类型的驱动器(固态驱动器或硬盘驱动器)?在嗅探器中,您是否在响应中看到 200 OK 的状态?延迟是因为 AppendToFile 还是 jason 反序列化?
  • @jdweng,我在嗅探器中看到每个请求的状态 200 OK。我找到了解决方案。我将发布代码。

标签: c# wpf api request duration


【解决方案1】:

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

【讨论】:

  • 你是对的;我想我有一些线程问题。因此,我将 HttpClientHelper post 方法更改为 async 方法。有用。我在下面的答案中的代码。
【解决方案2】:

我将我的 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.PostAsync() 方法必须为我的问题运行异步。我认为这与一些线程管理问题有关。但是这段代码现在对我有用。

【讨论】:

  • Run Async 应该与解决问题无关。可能是你超时了,或者服务器关闭了,它终于出现了,所以你的代码正在运行。
猜你喜欢
  • 2013-10-24
  • 2021-11-10
  • 1970-01-01
  • 2011-01-28
  • 1970-01-01
  • 1970-01-01
  • 2017-09-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多