ASP.NET 页面中的异步 C# 方法调用适用于调试,但不适用于实时站点

发布于 2024-10-14 03:25:40 字数 1061 浏览 4 评论 0原文

好的,情况是这样的:

我有一个 Web 应用程序,其中包含有关我们销售员的客户的统计表,每一行都有一个迷你图,显示过去 12 个月销售数据的总体趋势。每个页面显示特定销售员的客户列表,其中一些可能拥有大量客户 = 大量行 = 大量迷你图(例如,其中一个有 125 个,需要 15 秒才能加载)。

因此,无法使用 jQuery Sparklines - 它们完全固定了访问页面的用户的 CPU用 IE 可以看到很多迷你图。

因此,我转而使用 Google Chart API,它的效果要好得多,但有两个问题:1)它位于一个安全站点上,并且 Google Chart API URL 仅通过 HTTP 提供服务(通过使用一个小型包装脚本动态下载图表并从我们的安全服务器重新提供它来解决); 2) 在具有 125 个迷你图的页面上,由于请求数量的原因,它仍然非常慢(即使使用 0-9 服务器前缀来最大化可用连接数)。

因此,除此之外,我的下一步是尝试使每个“下载/抓取/重新提供图像”方法调用异步 - 并且它有效!

...但仅限于在调试模式下运行的我的开发盒。

当我将其推送到实时站点时,速度更快,但它留下了一些图像卸载,这当然是不可接受的。

所以这就是我希望一些大佬知道的:

1)为什么我的异步方法调用在调试时可以工作,但在实时站点上却不能工作?

2)有没有更简单的方法可以在安全服务器上快速加载大量某种类型的迷你图,而不会让我想抓狂?

2a.) 有人有使用 ASP.NET 图表库的经验吗?这是我应该调查的事情吗?

2b.) 一位同事建议我使用 1x1 CSS 背景图像并改变高度来制作自己的迷你图例程。问题是:a)如果我们想要进行更改,它是完全不可扩展的; b) 看起来很老套(标记中的每个迷你图留下大约数十亿个 DIV); c) 我不知道当一页上有 100-200 个精灵时它是否足够快 - 您对 1x1 精灵方法的可行性有何看法?

提前致谢。

OK Here is the situation:

I have a web app with a table of statistics on our salesmen's customers, and each row has a sparkline graph showing the general trend of the sales data for the last 12 months. Each page shows a particular salesman's customer list, and some of them can have an enormous number of customers = an enormous number of rows = an enormous number of sparklines (e.g. one in particular has 125 and takes 15 seconds to load).

For this reason, jQuery sparklines could not be used - they completely pinned the CPU of a user accessing a page with a lot of sparklines with IE.

So I moved on to using the Google Chart API, which worked much better, except for two issues: 1) it's on a secure site, and the Google Chart API URL is only served over HTTP (solved by using a small wrapper script to download the graph dynamically and re-serve it from our secure server); and 2) on a page with 125 sparklines, it was still very slow due to the number of requests (even when the 0-9 server prefixes are used to maximize the # of available connections).

So my next step beyond this was to try to make each of the "download/grab/re-serve image" method calls asynchronous - and it worked!

...but only on my dev box running in debug mode.

When I pushed it up to the live site, it was faster, but it left some of the images unloaded, which is of course unacceptable.

So here is what I was hoping some SO hotshot would know:

1) Why are my asynchronous method calls working while debugging, but not working on the live site?

2) Is there any easier way to get a large number of sparklines of some sort to load quickly on a secure server without making me want to tear my hair out?

2a.) Does anyone have any experience using the ASP.NET Chart Library? Is this something I should investigate?

2b.) A co-worker suggested I make my own sparkline routine using a 1x1 CSS background image and varying the height. The problems are a) it is completely un-extensible in case we want to make changes; b) it seems hacky as hell (leaves about a bajillion DIVs per sparkline in the markup); and c) I have no idea if it will be fast enough when there are 100-200 of them on one page - what are your thoughts on the feasibility of the 1x1 sprite approach?

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

东京女 2024-10-21 03:25:40

首先,异步并不意味着更快,在您的情况下,如果不减慢速度,那也没有什么区别。

我只是要简化正在发生的事情,以便我可以更好地理解它。有一个页面加载 125-200 张图像。这些图像是动态生成的图表。这是否概括了正在发生的事情?如果是这样的话:

如果客户端有足够的带宽并且您的服务器可以处理请求并且您的服务器上有足够大的管道,那么加载这么多图像应该不是问题。那么延迟在哪里呢?是谷歌吗?或者你的服务器速度变慢了吗?

与从浏览器直接访问 Google 相比慢了多少?
从浏览器直接访问 Google 的响应时间是否可以接受?
如果没有,您可能需要在 UI 中使用不同的策略,这样所有图像都不会自动加载。或者每个客户都在一个选项卡中或将内容分成几页,因此一次只请求少量数据和图像。

无论您生成多少个线程,您使用的 Http 套接字都将被限制为在任何时候向 Google 发出 2 个请求。有一种方法可以更改这个数字(但我不记得如何更改)。无论如何,这很可能是导致你的速度变慢的原因。

从业务层代码使用异步调用(在本例中执行一些 I/O 绑定操作)并不能让您获得释放请求线程来服务其他请求的好处。为此,您需要使用异步页面,因为该页面可以将此事实告知 IIS。任何其他异步工作只是使用更多线程(除非您使用异步 CTP - C# 5.0 中使用的技术,并且专门使用 I/O 线程而不是工作线程。

现在根据您所看到的情况,存在错误从 Google 获取图像时的服务器端,您需要知道这些错误是什么,我建议您不要使用异步。

First of all asynchronous doesn't mean faster and in your case it will make no difference if not slow things down even more.

I'm just going to simplify what's going on so I can understand it better. There is a page that loads 125-200 images. These images are dynamically generated graphs. Does that sum up what is going on? If so then:

Loading those many images should not be a problem if the client has sufficient bandwidth and your server can handle the requests and you have a large enough pipe on your server. So where is the delay? Is it Google? Or is your server slowing things down?

how much slower is it as compared to going from browser directly to Google?
Are the response times of going from browser directly to Google acceptable?
If not maybe you need to use a different strategy in your UI such that all images are not loaded automatically. Or each customer is in a tab or break things up into pages so only small amounts of data and therefore images are requested at a time.

The Http socket you're using will be limited to issuing 2 requests to Google at any time, no matter how mant threads you spawn. There is a way to change this number (but I can't remember off the top of my head how). Anyway, this is most likely the cause of your slowdown.

Using Asynchronous calls (to do some I/O bound operations as in this case) from business layer code is not getting you the benefit of free up the request thread to service other requests. For that to work you'll need to use async pages since the page can inform IIS of this fact. Any other async work simply uses more threads (unless you're using the techniques used in the Async CTP - C# 5.0 and a specifically using I/O threads and not worker threads.

Now given what you're seeing, there are errors on the server side at the time of getting the images from Google and you need to know what those errors are. I would recommended you not use async for this.

杯别 2024-10-21 03:25:40

根据我的经验,ASP.Net 图表效果很好。有一个快速入门 http://betterdashboards.wordpress.com/2010/02/21/how-to-create-a-sparkline-chart-in-asp-net/ 让您开始进行渲染所需的配置迷你图。

编辑:添加了在 MVC 中使用 ASP.Net 图表的示例。显然,您希望将其中一些代码移至某种类型的帮助程序类中,但希望这可以清楚地说明要完成这项工作需要做什么。

    @model IEnumerable<CustomerSales>        
@using Chart = System.Web.UI.DataVisualization.Charting.Chart   
@{    
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table>
    <tr>
        <th>
            Name
        </th>
        <th>
            Sales
        </th>
    </tr>

@foreach (var item in Model)
{
    <tr>
        <td>
            @item.Name
        </td>
        <td>
            @{

    var chart = new Chart();
    chart.ChartAreas.Add(new ChartArea());
    chart.ChartAreas[0].AxisX.LabelStyle.Enabled = false;
    chart.ChartAreas[0].AxisY.LabelStyle.Enabled = false;
    chart.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
    chart.ChartAreas[0].AxisY.MajorGrid.Enabled = false;
    chart.ChartAreas[0].AxisX.MajorTickMark.Enabled = false;
    chart.ChartAreas[0].AxisY.MajorTickMark.Enabled = false;
    chart.ChartAreas[0].AxisX.LineWidth = 0;
    chart.ChartAreas[0].AxisY.LineWidth = 0;

    chart.Series.Add(new Series());
        // Assign the random number to the chart to create 35 points
    for (int x = 0; x < item.Sales.Length; x++)
    {
        chart.Series[0].Points.AddXY(x, item.Sales[x]);
    }

     // Start hiding both sets of axes, labels, gridlines and tick marks
     chart.ChartAreas[0].AxisX.LabelStyle.Enabled = false;
     chart.ChartAreas[0].AxisY.LabelStyle.Enabled = false;
     chart.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
     chart.ChartAreas[0].AxisY.MajorGrid.Enabled = false;
     chart.ChartAreas[0].AxisX.MajorTickMark.Enabled = false;
     chart.ChartAreas[0].AxisY.MajorTickMark.Enabled = false;
     chart.ChartAreas[0].AxisX.LineWidth = 0;
     chart.ChartAreas[0].AxisY.LineWidth = 0;

     // Sparklines use the 'Spline' chart type to show a smoother trend with a line chart
     chart.Series[0].ChartType = SeriesChartType.Spline;

     // Since the line is the only thing you see on the chart, you might want to
     // increase its width.  Interestingly, you need to set the BorderWidth property
     // in order to accomplish that.
     chart.Series[0].BorderWidth = 2;

     // Re-adjust the size of the chart to reduce unnecessary white space
     chart.Width = 400;
     chart.Height = 100;
     string base64;
     using (MemoryStream ms = new MemoryStream())
     {
         chart.SaveImage(ms);
         var bytes = ms.GetBuffer();
         base64 = Convert.ToBase64String(bytes);
     }
 /**
  * Here's a simpler example that would do a regular chart, 
  * rather than a sparkline. No way to make the gridlines and axes go
  * away with this helper that I'm aware of.

    var chart = new Chart(
        width: 300,
        height: 100
        )
        .AddSeries(chartType: "Spline", yValues: item.Sales);
    var bytes = chart.GetBytes();
    var base64 = Convert.ToBase64String(bytes);    
             */
                }
             <img src="data:image/jpeg;base64,@base64" />
        </td>
    </tr>
}

</table>

这是使用如下所示的模型:

public class CustomerSales
{
    public CustomerSales(string name, params int[] sales)
    {
        Name = name;
        Sales = sales;
    }
    [Required]
    public string Name { get; set; }
    [Required]
    public int[] Sales { get; set; }
}

ASP.Net Charts work well in my experience. There's a quick starter at http://betterdashboards.wordpress.com/2010/02/21/how-to-create-a-sparkline-chart-in-asp-net/ to get you started with the necessary configuration to render a sparkline.

EDIT: Added sample of using ASP.Net charts in MVC. Obviously you'd want to move some of this code into a helper class of some kind, but hopefully this makes it clear what has to happen to make this work.

    @model IEnumerable<CustomerSales>        
@using Chart = System.Web.UI.DataVisualization.Charting.Chart   
@{    
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table>
    <tr>
        <th>
            Name
        </th>
        <th>
            Sales
        </th>
    </tr>

@foreach (var item in Model)
{
    <tr>
        <td>
            @item.Name
        </td>
        <td>
            @{

    var chart = new Chart();
    chart.ChartAreas.Add(new ChartArea());
    chart.ChartAreas[0].AxisX.LabelStyle.Enabled = false;
    chart.ChartAreas[0].AxisY.LabelStyle.Enabled = false;
    chart.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
    chart.ChartAreas[0].AxisY.MajorGrid.Enabled = false;
    chart.ChartAreas[0].AxisX.MajorTickMark.Enabled = false;
    chart.ChartAreas[0].AxisY.MajorTickMark.Enabled = false;
    chart.ChartAreas[0].AxisX.LineWidth = 0;
    chart.ChartAreas[0].AxisY.LineWidth = 0;

    chart.Series.Add(new Series());
        // Assign the random number to the chart to create 35 points
    for (int x = 0; x < item.Sales.Length; x++)
    {
        chart.Series[0].Points.AddXY(x, item.Sales[x]);
    }

     // Start hiding both sets of axes, labels, gridlines and tick marks
     chart.ChartAreas[0].AxisX.LabelStyle.Enabled = false;
     chart.ChartAreas[0].AxisY.LabelStyle.Enabled = false;
     chart.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
     chart.ChartAreas[0].AxisY.MajorGrid.Enabled = false;
     chart.ChartAreas[0].AxisX.MajorTickMark.Enabled = false;
     chart.ChartAreas[0].AxisY.MajorTickMark.Enabled = false;
     chart.ChartAreas[0].AxisX.LineWidth = 0;
     chart.ChartAreas[0].AxisY.LineWidth = 0;

     // Sparklines use the 'Spline' chart type to show a smoother trend with a line chart
     chart.Series[0].ChartType = SeriesChartType.Spline;

     // Since the line is the only thing you see on the chart, you might want to
     // increase its width.  Interestingly, you need to set the BorderWidth property
     // in order to accomplish that.
     chart.Series[0].BorderWidth = 2;

     // Re-adjust the size of the chart to reduce unnecessary white space
     chart.Width = 400;
     chart.Height = 100;
     string base64;
     using (MemoryStream ms = new MemoryStream())
     {
         chart.SaveImage(ms);
         var bytes = ms.GetBuffer();
         base64 = Convert.ToBase64String(bytes);
     }
 /**
  * Here's a simpler example that would do a regular chart, 
  * rather than a sparkline. No way to make the gridlines and axes go
  * away with this helper that I'm aware of.

    var chart = new Chart(
        width: 300,
        height: 100
        )
        .AddSeries(chartType: "Spline", yValues: item.Sales);
    var bytes = chart.GetBytes();
    var base64 = Convert.ToBase64String(bytes);    
             */
                }
             <img src="data:image/jpeg;base64,@base64" />
        </td>
    </tr>
}

</table>

This is using a model that looks like:

public class CustomerSales
{
    public CustomerSales(string name, params int[] sales)
    {
        Name = name;
        Sales = sales;
    }
    [Required]
    public string Name { get; set; }
    [Required]
    public int[] Sales { get; set; }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文