Я где-то слышал, что C # 5 async-await будет настолько крутым, что вам не придется беспокоиться об этом:
if (InvokeRequired)
{
BeginInvoke(...);
return;
}
// do your stuff here
Похоже, что обратный вызов операции ожидания произойдет в исходном потоке вызывающей стороны. Эрик Липперт и Андерс Хейлсберг неоднократно заявляли, что эта функция возникла из-за необходимости сделать пользовательские интерфейсы (особенно пользовательские интерфейсы сенсорных устройств) более отзывчивыми.
Я думаю, что обычное использование такой функции будет что-то вроде этого:
public class Form1 : Form
{
// ...
async void GetFurtherInfo()
{
var temperature = await GetCurrentTemperatureAsync();
label1.Text = temperature;
}
}
Если используется только обратный вызов, то установка текста метки вызовет исключение, поскольку он не выполняется в потоке пользовательского интерфейса.
До сих пор я не мог найти какой-либо ресурс, подтверждающий, что это так. Кто-нибудь знает об этом? Есть ли какие-либо документы, объясняющие технически, как это будет работать?
Пожалуйста, предоставьте ссылку из надежного источника, а не просто отвечайте "да".
источник
await
функциональности. Это просто много синтаксического сахара для продолжения прохождения . Возможно, есть какие-то другие не связанные улучшения WinForms, которые должны помочь? Это относится к самой платформе .NET, а не к C #.Ответы:
Я думаю, вы запутались здесь. То, о чем вы просите, уже возможно с помощью
System.Threading.Tasks
,async
иawait
в C # 5 просто предоставим немного более приятного синтаксического сахара для той же функции.Давайте использовать пример Winforms - перетащите кнопку и текстовое поле на форму и используйте этот код:
Запустите его, и вы увидите, что (а) он не блокирует поток пользовательского интерфейса и (б) вы не получите обычную ошибку «операция с несколькими потоками не действительна» - если вы не удалите
TaskScheduler
аргумент из последнегоContinueWith
, в в каком случае вы будете.Это стандартное продолжение передачи . Магия происходит в
TaskScheduler
классе и, в частности, в экземпляре, полученном с помощьюFromCurrentSynchronizationContext
. Передайте это в любое продолжение, и вы скажете, что продолжение должно выполняться в том потоке, который вызвалFromCurrentSynchronizationContext
метод - в данном случае, в потоке пользовательского интерфейса.Ожидатели немного более сложные в том смысле, что они знают, с какого потока они начали и с какого потока должно происходить продолжение. Таким образом, приведенный выше код может быть написан немного более естественно:
Эти два должны выглядеть очень похожи, и на самом деле они являются очень похожи.
DelayedAddAsync
Теперь метод возвращаетTask<int>
вместоint
, и поэтомуawait
просто хлопая продолжения на каждом из них. Основное отличие состоит в том, что он передает контекст синхронизации в каждой строке, поэтому вам не нужно делать это явно, как мы это делали в последнем примере.Теоретически различия гораздо более значительны. Во втором примере каждая отдельная строка в
button1_Click
методе фактически выполняется в потоке пользовательского интерфейса, но сама задача (DelayedAddAsync
) выполняется в фоновом режиме. В первом примере все работает в фоновом режиме , за исключением присвоения, кtextBox1.Text
которому мы явно привязали контекст синхронизации потока пользовательского интерфейса.Вот что действительно интересно
await
- тот факт, что ожидающий может подключаться и выходить из одного и того же метода без каких-либо блокирующих вызовов. Вы звонитеawait
, текущий поток возвращается к обработке сообщений, и когда это будет сделано, официант подберет именно то место, где остановился, в том же потоке, в котором остановился. Но с точки зрения вашегоInvoke
/BeginInvoke
контраста в вопросе, я Мне жаль говорить, что вы должны были перестать делать это давным-давно.источник
ArrayList
класс в новом коде. У меня все еще нет опыта работы с RX. Люди узнают, что им нужно знать, и делятся тем, что они уже знают, даже если то, что они уже знают, устарело. Этот ответ может быть устаревшим через несколько лет.Да, для потока пользовательского интерфейса обратный вызов операции ожидания будет происходить в исходном потоке вызывающей стороны.
Год назад Эрик Липперт написал серию из восьми статей, рассказывающих об этом: Fabulous Adventures In Coding
РЕДАКТИРОВАТЬ: и вот Андерс // build / presentation: channel9
Кстати, вы заметили, что если вы перевернете "// build /" вверх ногами, вы получите "/ plinq //" ;-)
источник
Джон Скит (Jon Skeet) дал отличную презентацию, охватывающую методы Async в C # 5, которая может оказаться чрезвычайно полезной:
http://skillsmatter.com/podcast/home/async-methods
источник