Асинхронные вызовы методов C # на странице ASP.NET, работающие на отладке, но не работающие на живом сайте - PullRequest
2 голосов
/ 26 января 2011

ОК. Вот ситуация:

У меня есть веб-приложение со статистической таблицей клиентов наших продавцов, и в каждой строке есть спарклайн-график, показывающий общую тенденцию данных о продажах за последние 12 месяцев. На каждой странице показан список клиентов конкретного продавца, и у некоторых из них может быть огромное количество клиентов = огромное количество строк = огромное количество спарклайнов (например, у одного, в частности, 125 и для загрузки требуется 15 секунд).

По этой причине jQuery sparklines нельзя было использовать - они полностью закрепили ЦП пользователя, получающего доступ к странице с большим количеством спарклайнов в IE.

Поэтому я перешел к использованию Google Chart API , который работал намного лучше, за исключением двух проблем: 1) он находится на защищенном сайте, а URL-адрес API Google Chart API подается только по HTTP ( решается с помощью небольшого скрипта-обертки для динамической загрузки графика и его повторного использования с нашего защищенного сервера); и 2) на странице со 125 спарклайнами она все еще была очень медленной из-за количества запросов (даже когда префиксы сервера 0-9 используются для максимизации количества доступных соединений).

Поэтому следующим шагом для меня было попытаться сделать каждый из вызовов метода «загрузить / перехватить / восстановить изображение» асинхронным - и это сработало!

... но только на моем устройстве dev, работающем в режиме отладки.

Когда я переместил его на сайт в реальном времени, он работал быстрее, но некоторые изображения оставались незагруженными, что, конечно, недопустимо.

Так вот что я надеялся, что некоторые ТАК узнают:

1) Почему мои асинхронные вызовы методов работают во время отладки, но не работают на работающем сайте?

2) Есть ли какой-нибудь более простой способ заставить большое количество искровых линий быстро загружаться на защищенный сервер, не заставляя меня рвать на себе волосы?

2a.) У кого-нибудь есть опыт использования библиотеки диаграмм ASP.NET? Это то, что я должен исследовать?

2b.) Сотрудник предложил мне создать собственную процедуру спарклайна, используя фоновое изображение CSS 1x1 и изменяя высоту. Проблемы в том, что: а) это абсолютно невозможно расширить, если мы хотим внести изменения; б) кажется чертовски хакерским (оставляет в разметке около 36 миллиардов DIV на спарклайн); и в) я понятия не имею, будет ли это достаточно быстро, когда их будет 100-200 на одной странице - что вы думаете о целесообразности использования спрайта 1x1?

Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 26 января 2011

Прежде всего, асинхронность не означает ускорение, и в вашем случае это не будет иметь значения, если не замедлит работу еще больше.

Я просто собираюсь упростить то, что происходит, чтобы лучше понять это. Есть страница, которая загружает 125-200 изображений. Эти изображения являются динамически генерируемыми графиками. Это подводит итог того, что происходит? Если так, то:

Загрузка этих многих изображений не должна быть проблемой, если клиент имеет достаточную пропускную способность, и ваш сервер может обрабатывать запросы, и у вас достаточно большой канал на вашем сервере. Так где же задержка? Это гугл? Или ваш сервер замедляет работу?

насколько медленнее, чем переход из браузера прямо в Google? Приемлемо ли время отклика перехода из браузера непосредственно в Google? Если нет, возможно, вам нужно использовать другую стратегию в вашем пользовательском интерфейсе, чтобы все изображения не загружались автоматически. Или каждый клиент находится на вкладке или разбивает вещи на страницы, поэтому за один раз запрашиваются только небольшие объемы данных и, следовательно, изображений.

Используемый вами сокет Http будет ограничен отправкой 2 запросов в Google в любое время, независимо от того, какие потоки вы создаете. Есть способ изменить это число (но я не могу вспомнить, как это происходит). Во всяком случае, это, скорее всего, причина вашего замедления.

Использование асинхронных вызовов (для выполнения некоторых операций, связанных с вводом / выводом, как в этом случае) из кода бизнес-уровня, не дает вам возможности освободить поток запросов для обслуживания других запросов. Чтобы это работало, вам нужно использовать асинхронные страницы, поскольку страница может информировать IIS об этом факте. Любая другая асинхронная работа просто использует больше потоков (если вы не используете методы, используемые в Async CTP - C # 5.0, и специально используете потоки ввода-вывода, а не рабочие потоки.

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

1 голос
/ 26 января 2011

ASP.Net Графики хорошо работают в моем опыте.В http://betterdashboards.wordpress.com/2010/02/21/how-to-create-a-sparkline-chart-in-asp-net/ есть быстрый старт, чтобы вы начали работу с необходимой конфигурацией для визуализации спарклайна.

РЕДАКТИРОВАТЬ: Добавлен пример использования диаграмм ASP.Net в MVC.Очевидно, вы захотите переместить часть этого кода в некоторый вспомогательный класс, но, надеюсь, это прояснит, что должно произойти, чтобы эта работа работала.

    @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.&nbsp; 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; }
}
...