Что делает новая функция ожидания C#? [закрытый]
может ли кто-нибудь объяснить, что такое
5 ответов:
они просто говорили об этом в PDC вчера!
Await используется в сочетании с задачами (параллельное программирование) в .NET. это ключевое слово вводится в следующей версии .NET. It более или менее позволяет "приостановить" выполнение метода, чтобы дождаться завершения выполнения задачи. Вот краткий пример:
//create and run a new task Task<DataTable> dataTask = new Task<DataTable>(SomeCrazyDatabaseOperation); //run some other code immediately after this task is started and running ShowLoaderControl(); StartStoryboard(); //this will actually "pause" the code execution until the task completes. It doesn't lock the thread, but rather waits for the result, similar to an async callback // please so also note, that the task needs to be started before it can be awaited. Otherwise it will never return dataTask.Start(); DataTable table = await dataTask; //Now we can perform operations on the Task result, as if we're executing code after the async operation completed listBoxControl.DataContext = table; StopStoryboard(); HideLoaderControl();
в основном
async
иawait
ключевые слова позволяют указать, что выполнение метода должно прекращаться при всех использованияхawait
, который помечает вызовы асинхронного метода, а затем возобновляется после завершения асинхронной операции. Это позволяет вызывать метод в основном потоке приложения и обрабатывать сложную работу асинхронно, без необходимости явно определять потоки и соединения или блокировать основной поток приложения.подумайте об этом как о чем-то похожем на a
yield return
оператор в методе, производящем IEnumerable. Когда среда выполнения попадает вyield
, это в основном сохранит текущее состояние метода и вернет полученное значение или ссылку. В следующий раз IEnumerator.MoveNext () вызывается для возвращаемого объекта (который генерируется внутри среды выполнения), старое состояние метода восстанавливается в стек и выполнение продолжается со следующей строки послеyield return
как будто мы никогда не покидали метод. Без этого ключевого слова тип IEnumerator должен быть определен Пользователем для хранения состояния и обработки запросов итерации с помощью методов, которые могут стать очень сложными.аналогично, метод помечен как
async
должен быть хотя бы одинawait
. На Анawait
, среда выполнения сохранит состояние текущего потока и стек вызовов, выполнит асинхронный вызов и развернется обратно в цикл сообщений среды выполнения, чтобы обработать следующее сообщение и сохранить отзывчивость приложения. По завершении асинхронной операции при следующем планировании возможность, стек вызовов для выполнения асинхронной операции возвращается и продолжается, как если бы вызов был синхронным.Итак, эти два новых ключевых слова в основном упрощают кодирование асинхронных процессов, так же как
yield return
упрощена генерация пользовательских перечислений. С парой ключевых слов и небольшим фоновым знанием вы можете пропустить все запутанные и часто подверженные ошибкам детали традиционного асинхронного шаблона. Это будет бесценно в значительной степени любой событийных GUI-приложения как приложения WinForms, в WPF и Silverlight.
в настоящее время принимаются ответ вводит в заблуждение.
await
ничего не останавливаясь. Прежде всего, он может использоваться только в методах или лямбдах, помеченных какasync
и возвратTask
илиvoid
если вам все равно, имеяTask
экземпляр, работающий в этом методе.вот пример:
internal class Program { private static void Main(string[] args) { var task = DoWork(); Console.WriteLine("Task status: " + task.Status); Console.WriteLine("Waiting for ENTER"); Console.ReadLine(); } private static async Task DoWork() { Console.WriteLine("Entered DoWork(). Sleeping 3"); // imitating time consuming code // in a real-world app this should be inside task, // so method returns fast Thread.Sleep(3000); await Task.Run(() => { for (int i = 0; i < 10; i++) { Console.WriteLine("async task iteration " + i); // imitating time consuming code Thread.Sleep(1000); } }); Console.WriteLine("Exiting DoWork()"); } }
выход:
Вошел DoWork (). Спит 3
асинхронная итерация задачи 0
Состояние задачи: WaitingForActivation
Ожидание для ENTER
асинхронных задач повторение 1
асинхронная итерация задачи 2
асинхронная итерация задачи 3
асинхронная итерация задачи 4
асинхронная итерация задачи 5
асинхронная итерация задачи 6
асинхронная итерация задачи 7
асинхронная итерация задачи 8
асинхронная итерация задачи 9
Выход Из DoWork ()
для тех, кто новичок в асинхронном программировании в .NET, вот (полностью поддельная) аналогия в сценарии, с которым вы можете быть более знакомы - AJAX-вызовы с использованием JavaScript/jQuery. Простой пост jQuery AJAX выглядит так:
$.post(url, values, function(data) { // AJAX call completed, do something with returned data here });
причина, по которой мы обрабатываем результаты в функции обратного вызова, заключается в том, что мы не блокируем текущий поток, ожидая возврата вызова AJAX. Только когда ответ будет готов, обратный вызов будет запущен, освобождая текущий поток для выполнения других задач среднее время.
теперь, если JavaScript поддерживает
await
ключевое слово (что, конечно, не так (пока!)), вы могли бы достичь того же с этим:var data = await $.post(url, values); // AJAX call completed, do something with returned data here
это намного чище, но похоже, что мы ввели синхронный блокирующий код. Но (поддельный) компилятор JavaScript взял бы все после
await
и подключил его к обратному вызову, поэтому во время выполнения второй пример будет вести себя так же, как и первый.это может показаться не как будто это экономит вам много работы, но когда дело доходит до таких вещей, как обработка исключений и контекстов синхронизации, компилятор на самом деле делает много тяжелой работы для вас. Для большего, я бы рекомендовал часто задаваемые вопросы следовал по серия блогов Стивена Клири.
Если бы мне пришлось реализовать его на Java, это выглядело бы примерно так:
/** * @author Ilya Gazman */ public abstract class SynchronizedTask{ private ArrayList<Runnable> listeners = new ArrayList<Runnable>(); private static final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(6, 6, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1000)); public final void await(Runnable listener){ synchronized (this) { listeners.add(listener); } } public void excecute(){ onExcecute(); for (int i = listeners.size() - 1; i >= 0; i--) { Runnable runnable; synchronized (this) { runnable = listeners.remove(i); } threadPoolExecutor.execute(runnable); } } protected abstract void onExcecute(); }
ваше приложение будет использовать его в таком виде:
public class Test{ private Job job = new Job(); public Test() { craeteSomeJobToRunInBackground(); methode1(); methode2(); } private void methode1(){ System.out.println("Running methode 1"); job.await(new Runnable() { @Override public void run() { System.out.println("Continue to running methode 1"); } }); } private void methode2(){ System.out.println("Running methode 2"); } private void craeteSomeJobToRunInBackground() { new Thread(new Runnable() { @Override public void run() { job.excecute(); } }).start(); } private class Job extends SynchronizedTask{ @Override protected void onExcecute() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Job is done"); } } }