Опубликован: 11.09.2006 | Уровень: специалист | Доступ: свободно
Лекция 7:

Асинхронное программирование

Асинхронный запуск произвольного метода

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

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

Создайте новое Windows-приложение и назовите его ArbitraryMethod. Добавляем на форму три надписи, два текстовых поля и одну кнопку, и устанавливаем им следующие свойства:

button1, свойство Значение
Name BtnRun
Location 16; 64
Text Сумма
label1, свойство Значение
Name LblA
Location 8; 24
Size 72; 23
Text Значение А
label2, свойство Значение
Name LblB
Location 216; 24
Size 72; 23
Text Значение В
label3, свойство Значение
Name LblResult
Location 128; 64
Size 272; 23
Text
textBox1, свойство Значение
Name TxbA
Location 88; 24
Text
textBox2, свойство Значение
Name TxbB
Location 296; 24
Text

Устанавливаем свойству Size формы значение 424; 144 и заголовок "Асинхронный запуск произвольного метода". Переходим в код формы. Создание делегата в данном случае ничем не отличается от общих правил, рассмотренных в "Введение в windows-формы" :

// Делегат, принимающий две переменные типа int и возвращающий одну переменную типа int,
// для асинхронного запуска метода (Summ)

private delegate int AsyncSumm(int a, int b);
Листинг 7.4.

Создаем метод Summ, в котором будут складываться числа, вводимые в два текстовых поля:

private int Summ(int a, int b)
	{
		return a+b;
	}

Обработчик кнопки btnRun будет выглядеть следующим образом:

private void btnRun_Click(object sender, System.EventArgs e)
	{
		int a, b;
		try
		{
			// Преобразование типов данных.
			a = Int32.Parse(txbA.Text);
			b = Int32.Parse(txbB.Text);
		}
		catch(Exception)
		{
			MessageBox.Show("При выполнении преобразования типов возникла ошибка");
			txbA.Text = txbB.Text = "";
			return;
		}
		AsyncSumm summdelegate = new AsyncSumm(Summ);
		AsyncCallback cb = new AsyncCallback(CallBackMethod);
		summdelegate.BeginInvoke(a, b, cb, summdelegate);
	}
Листинг 7.5.

Мы создали экземпляр summdelegate делегата AsyncSumm и проинициализировали его методом Summ:

AsyncSumm summdelegate = new AsyncSumm(Summ);

Для использования механизма Сallback создали экземпляр делегата AsyncCallBack:

AsyncCallback cb = new AsyncCallback(CallBackMethod);

Метод CallBackMethod имеет сигнатуру, принимающую один параметр типа IAsyncResult и не возвращающую значений. После того как делегат инициализирован методом, можно запускать прикрепленный к делегату метод асинхронно с помощью метода BeginInvoke. Этот метод принимает две переменные типа int а и b, экземпляр cb делегата AsyncCallback и экземпляр summdelegate делегата SummDelegate:

summdelegate.BeginInvoke(a, b, cb, summdelegate);

Создаем метод CallBackMethod, который привязан к делагату summdelegate:

private void CallBackMethod(IAsyncResult ar)
 {
   AsyncSumm summdelegate = (AsyncSumm)ar.AsyncState;
   lblResult.Text = String.Format("Сумма введенных чисел равна {0}", summdelegate.EndInvoke(ar));
 }
Листинг 7.6.

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

При запуске приложения после ввода чисел и нажатия кнопки "Сумма" метод EndInvoke возвращает результат в надпись (рис. 7.3).

Приложение ArbitraryMethod

Рис. 7.3. Приложение ArbitraryMethod

На диске, прилагаемом к книге, вы найдете приложение ArbitraryMethod (Code\Glava7\ ArbitraryMethod).

Елена Дьяконова
Елена Дьяконова

При нажатии на Сумма в примере ArbitraryMethod из Лекция 7, VS 2013 выдается ошибка: 

Необработанное исключение типа "System.InvalidOperationException" в System.Windows.Forms.dll

Дополнительные сведения: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления "lblResult" не из того потока, в котором он был создан.

Затем:

Необработанное исключение типа "System.InvalidOperationException" в mscorlib.dll

Дополнительные сведения: Для каждой асинхронной операции метод EndInvoke может вызываться только один раз.

Александр Сороколет
Александр Сороколет

Свойство WindowState формы blank Maximized. Не открывается почемуто на всё окно, а вот если последующую форму бланк открыть уже на макс открывается :-/