Используя WebClient в рамках ASP.NET MVC асинхронно?

Стек намного быстрее. Это буквально только использует единственную инструкцию относительно большей части архитектуры, в большинстве случаев, например, относительно x86:

sub esp, 0x10

(Который спускает указатель вершины стека 0x10 байтами и таким образом "выделяет" те байты для использования переменной.)

, Конечно, размер стека очень, очень конечен, как Вы быстро узнаете, злоупотребляете ли Вы выделение стека или пытаетесь сделать рекурсию:-)

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

Мое эмпирическое правило: если я знаю, что собираюсь нуждаться в некоторых данных во время компиляции , и они находятся под несколькими сотнями байтов в размере, я складываю - выделяют его. Иначе я помещаю в "кучу" - выделяют его.

8
задан Brian Vallelunga 8 August 2009 в 15:43
поделиться

2 ответа

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

Я бы использовал что-то вроде этого (используя шаблон событий, как описано в эта статья ):

public class MyAsyncController : AsyncController
{
    // The async framework will call this first when it matches the route
    public void MyAction()
    {
        // Set a default value for our result param
        // (will be passed to the MyActionCompleted method below)
        AsyncManager.Parameters["webClientResult"] = "error";
        // Indicate that we're performing an operation we want to offload
        AsyncManager.OutstandingOperations.Increment();

        var client = new WebClient();
        client.DownloadStringCompleted += (s, e) =>
        {
            if (!e.Cancelled && e.Error == null)
            {
                // We were successful, set the result
                AsyncManager.Parameters["webClientResult"] = e.Result;
            }
            // Indicate that we've completed the offloaded operation
            AsyncManager.OutstandingOperations.Decrement();
        };
        // Actually start the download
        client.DownloadStringAsync(new Uri("http://www.apple.com"));
    }

    // This will be called when the outstanding operation(s) have completed
    public ActionResult MyActionCompleted(string webClientResult)
    {
        ViewData["result"] = webClientResult;
        return View();
    }
}

И убедитесь, что вы настроили все необходимые маршруты, например (в Global.asax.cs):

public class MvcApplication : System.Web.HttpApplication
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapAsyncRoute(
            "Default",
            "{controller}/{action}/{id}",
            new { controller = "Home", action = "Index", id = "" }
        );
    }
}
7
ответ дан 5 December 2019 в 17:39
поделиться

Метод DownloadStringAsync использует модель событий, вызывая DownloadStringCompleted по завершении. Вы также можете остановить запрос, если он выполняется слишком долго, вызвав WebClient.CancelAsync () . Это позволит вашему потоку основного запроса и потоку WebClient работать параллельно, и позволит вам точно решить, сколько времени вы хотите, чтобы основной поток ждал перед возвратом.

В приведенном ниже примере мы инициируем загрузку и устанавливаем событие обработчик, который мы хотим вызвать по завершении. DownloadStringAsync немедленно возвращается, так что мы можем продолжить обработку остальной части нашего запроса.

Чтобы продемонстрировать более детальный контроль над этой операцией, когда мы дойдем до конца действия нашего контроллера, мы можем проверить, завершена ли загрузка; если нет, дайте ему еще 3 секунды и затем прервите.

string downloadString = null;

ActionResult MyAction()
{
    //get the download location
    WebClient client = StartDownload(uri);
    //do other stuff
    CheckAndFinalizeDownload(client);
    client.Dispose();
}

WebClient StartDownload(Uri uri)
{
    WebClient client = new WebClient();
    client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(Download_Completed);
    client.DownloadStringAsync(uri);
    return client;
}

void CheckAndFinalizeDownload(WebClient client)
{
    if(this.downloadString == null)
    {
        Thread.Sleep(3000);
    }
    if(this.downloadString == null)
    {
        client.CancelAsync();
        this.downloadString = string.Empty;
    }
}

void Download_Completed(object sender, DownloadStringCompletedEventArgs e)
{
    if(!e.Cancelled && e.Error == null)
    {
        this.downloadString = (string)e.Result;
    }
}
3
ответ дан 5 December 2019 в 17:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: