2009-08-03 3 views
1

У меня есть одно заявление, запущенное на странице ASP.NET, которое занимает много времени (долгое время я имею в виду 100 мс, который слишком длинный, если я хочу, чтобы эта страница была молниеносной), и мне все равно, когда он выполняется до тех пор, пока выполняется.Самый простой способ сделать один оператор async в C#?

Каков наилучший способ (и, надеюсь, самый простой) для этого?

ответ

8

Самый простой способ, вероятно, заставить его выполнить в threadpool. Например, чтобы сделать это асинхронным:

using System; используя System.Нарезание резьбы;

class Test 
{ 
    static void ExecuteLongRunningTask() 
    { 
     Console.WriteLine("Sleeping..."); 
     Thread.Sleep(1000); 
     Console.WriteLine("... done"); 
    } 

    static void Main() 
    { 
     ExecuteLongRunningTask(); 
     Console.WriteLine("Finished"); 
     Console.ReadLine(); 
    } 
} 

Изменение первой линии Main к:

ThreadPool.QueueUserWorkItem(x => ExecuteLongRunningTask()); 

Имейте в виду, что если вы передаете какие-либо аргументы в, они будут захвачены переменные - которые могут иметь тонкие побочные эффекты в некоторых случаях (особенно если вы используете его в цикле).

+0

.. что я думал, пытаясь побить вас ..: D –

+0

Это сработало (по понятию), но что-то о выполнении этого кода в другом потоке разбило процесс. Я заменил Thread.Sleep, чтобы подтвердить, что у меня, по крайней мере, была правильная механика. Существуют ли какие-либо конкретные вещи ASP.NET, которые выходят из-под удара, когда вы используете этот подход? Например, этот код может читать web.config за кулисами. Это отбросит? – Larsenal

+0

Я получаю всевозможные интересные побочные эффекты. При попытке открыть файл System.Data.SqlClient.SqlConnection не работает сообщение «Ошибка входа в систему для пользователя ...» XYZ ». Интересные вещи для отслеживания. – Larsenal

0

Если вы хотите сказать, что ответ может быть отправлен до запуска команды, вы можете использовать ThreadPool.QueueUserWorkItem для запуска его в другом потоке без блокировки вашего запроса.

1

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

+0

Какой контекст поможет? Я не хотел, чтобы вопрос * был настолько узким, что это было бы бесполезно для потомков. – Larsenal

+0

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

3

Если это 100 мс, то не беспокойтесь. Ваши пользователи не могут обнаружить задержку в 100 мс.


Edit: некоторые пояснения.

Если я правильно помню, 100 миллисекунд (1/10 секунды) находятся в пределах минимального количества времени, которое человек может воспринимать. Итак, для обсуждения, позвольте мне сказать, что этот 100 мс может быть воспринят пользователями сайта OP, и что стоит повысить производительность на 100 мс. С самого начала я предполагал, что ОП правильно определил эту «долгосрочную» задачу как потенциальный источник улучшения в 100 мкс. Итак, почему я предложил ему проигнорировать это?

Работа с несколькими потоками должным образом непростая и является источником ошибок, которые трудно отследить. Добавление потоков к проблеме обычно не является решением, но скорее является источником других проблем, которые вы просто не нашли сразу (*).

У меня была возможность научиться этому трудному пути, с ошибкой, которую можно было воспроизвести только в самой быстрой системе с восьмью процессорами, доступной в то время, а затем только путем неустанного удара по предмету, одновременно моделируя степень из-за сбоя сети, что привело бы к тому, что сетевые администраторы были бы выстроены и расстреляны, если бы это произошло в реальной жизни. Ошибка оказалась в ядре Unix OS обработки сигналов, и речь шла о расположении нескольких инструкций.

Предоставлено Я никогда не видел ничего плохого с тех пор, я все еще видел, как многие разработчики спорили многопоточными ошибками. С одной стороны, этот вопрос, с одной стороны, требовал «простого выхода» через потоки, а с другой стороны, преимущество составляло всего 100 мс. Поскольку не показалось, что у ОП уже была хорошо протестированная инфраструктура потоковой передачи, мне показалось, что имеет смысл проигнорировать 100 мс или, возможно, повысить производительность каким-то другим способом.


(*) Конечно, есть много обстоятельств, где алгоритм выгодно может быть выполнены параллельно, и выполненные из нескольких потоков, работающий на нескольких ядер. Но это не похоже на то, что ОП имеет такой случай.

+0

Downvoter: Позаботьтесь о том, чтобы разделить причину понижения? –

+0

Почему вам так нравится Google? Я рад, что они не тратят 100 мс моего времени 50 раз в день. –

+1

Я отказался, потому что ваш ответ не является ответом на вопрос. ОП не спросил: «Я трачу время на оптимизацию на 100 мс?» он спросил, как он может снять задержка в 100 мс. Я создаю веб-службы облачного масштаба, и наше среднее время отклика должно быть значительно ниже 100 мс, игнорируя этот низкий висящий плод, который ОП уже идентифицировал, кажется ленивым. –

1

// This is the delegate to use to execute the process asynchronously 
public delegate void ExecuteBackgroundDelegate(); 

// 
[STAThread] 
static void Main(string[] args) 
{    
    MyProcess proc = new MyProcess(); 

    // create an instance of our execution delegate 
    ExecuteBackgroundDelegate asynchExec = new ExecuteBackgroundDelegate(proc.Execute); 

    // execute this asynchronously 
    asynchExec.BeginInvoke(null, null); 
} 
+0

Вы также можете просто действовать ... новое действие (() => proc.Execute) .BeginInvoke (null, null); –

+0

Вау, спасибо! Я не знал об этом. Я только что понял, что у меня нет ни одной ссылки на языке C#, начиная с 1.1. –

0

вы можете использовать ThreadPool.

ThreadPool.QueueUserWorkItem(o => Thread.Sleep(1000) /*your long task*/ ); 
0
class Test 
{ 
    void LongRunningTask() 
    { 
     Console.WriteLine("Sleeping..."); 
     Thread.Sleep(10000); 
     Console.WriteLine("... done"); 
    } 

    static void Main() 
    { 
     Test t = new Test(); 
     new Action(() => t.LongRunningTask()).BeginInvoke(null, t); 
    } 
} 
0

Я бы не возиться с любым из этого заправочного материала для 100мс задержки. Это будет делать хорошо:

protected void Page_Unload(object sender, EventArgs e) 
{ 
    HttpContext.Current.Response.Flush(); 
    HttpContext.Current.Response.Close(); 

    // Your code here 
} 

(копируется из моего предыдущего ответа на this question)

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