Вопрос по Курсу: "Параллельное программирование с использованием MS VisualStudia 2010". При компиляции Самостоятельного задания (одновременная отрисовка прямоугольников, эллипсов и выдача в текст-бокс случайного числа) среда предупреждает: suspend - устаревшая команда; примените monitor, mutex и т.п. Создаётся впечатление, что Задание создано в более поздней среде, чем VS 2010. |
Томский политехнический университет
Опубликован: 23.01.2013 | Доступ: свободный | Студентов: 1157 / 192 | Длительность: 12:09:00
Тема: Программирование
Специальности: Программист, Архитектор программного обеспечения
Теги:
Самостоятельная работа 7:
Создание многопоточного Silverlight - приложения
< Самостоятельная работа 6 || Самостоятельная работа 7 || Лекция 12 >
Аннотация: В рамках данного практического будет создан простой Silverlight проект, выполняющий асинхронно три различных потока.
- Создадим Silverlight приложение и назовем его "ThreadsSilverlightApplication":
- Разместим четыре элемента на форме (3 TextBlock и 1 Button) как показано на рисунке, и создадим у кнопки соответствующие событие:
XAML-код будет выглядеть следующим образом:
<UserControl x:Class="ThreadsSilverlightApplication.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <Grid x:Name="LayoutRoot" Background="BurlyWood"> <Button Height="23" HorizontalAlignment="Left" Margin="160,265,0,0" Name="StartButton" VerticalAlignment="Top" Width="81" Content="Запуск" Click="StartButton_Click" /> <TextBlock Height="23" HorizontalAlignment="Left" Margin="160,49,0,0" Name="Thread1TextBlock" VerticalAlignment="Top" Text="Первый поток"/> <TextBlock Height="23" HorizontalAlignment="Left" Margin="160,120,0,0" Name="Thread2TextBlock" VerticalAlignment="Top" Text="Второй поток" /> <TextBlock Height="23" HorizontalAlignment="Left" Margin="160,186,0,0" Name="Thread3TextBlock" VerticalAlignment="Top" Text="Третий поток"/> </Grid> </UserControl>
- Для того, что бы использовать многопоточность, добавим директиву в начало кода:
using System.Threading;
- Создадим три объекта класса Thread с типом private, как показано в листинге кода:
public partial class MainPage : UserControl { private Thread thread1; private Thread thread2; private Thread thread3; …
- Далее создадим три объекта класса TextBlock, для того чтобы в дальнейшем свойства ЭУ TexBlock (которые расположены на форме) были доступны в коде:
private static TextBlock _Thread1TextBlock; private static TextBlock _Thread2TextBlock; private static TextBlock _Thread3TextBlock;
- Создадим три переменных типа int и обнулим их:
private static int c1 = 0; private static int c2 = 0; private static int c3 = 0;
- Создадим переменную типа bool и присвоим ей значение true, т.к потоки еще не запущены:
private static bool done = true;
- Добавим свойство bool типа public (данное свойство понадобится для пункта 14):
public bool Done { get { return done; } set { done = value; } }
- В public MainPage() объектам класса TextBlock присвоим, соответствующим названиям ЭУ TextBlock, значения:
public MainPage() { InitializeComponent(); _Thread1TextBlock = Thread1TextBlock; _Thread2TextBlock = Thread2TextBlock; _Thread3TextBlock = Thread3TextBlock; }
- Создадим три статичных метода DoThread1(), DoThread2(), DoThread3(), которые в бесконечном цикле осуществляется операция приращения единицы - переменной, при каждой итерации:
public static void DoThread1() { while (!done) { c1++; _Thread1TextBlock.Dispatcher.BeginInvoke(delegate() { _Thread1TextBlock.Text = c1.ToString(); }); Thread.Sleep(100); } } public static void DoThread2() { while (!done) { c2++; _Thread2TextBlock.Dispatcher.BeginInvoke(delegate() { _Thread2TextBlock.Text = c2.ToString(); }); Thread.Sleep(150); } } public static void DoThread3() { while (!done) { c3++; _Thread3TextBlock.Dispatcher.BeginInvoke(delegate() { _Thread3TextBlock.Text = c3.ToString(); }); Thread.Sleep(200); } }
Использование метода BeginInvoke() является обязательным так, как необходимо изменить элемент графического интерфейса принадлежащего другому потоку (главному потоку, который всегда создается автоматически). Также в каждом созданном методе, добавлен метод Thread.Sleep(): для того, что бы приостанавливать выполнение потока не некоторое время (в нашем случае Thread.Sleep(100), Thread.Sleep(150), Thread.Sleep(200)).
- Теперь создать метод StartThreads(), который будет вызывать методы DoThread1(), DoThread2(), DoThread3(), в различных потоках:
private void StartThreads() { done = false; thread1 = new Thread(DoThread1); thread1.Start(); thread2 = new Thread(DoThread2); thread2.Start(); thread3 = new Thread(DoThread3); thread3.Start(); }
- Инициируем запуск потоков при нажатии на кнопку:
private void StartButton_Click(object sender, RoutedEventArgs e) { if (false == done) done = true; else StartThreads(); }
- Перейдем в файл App.xaml.cs. В обработчике события Application_Exit() добавим код, для того, что бы потоки завершили бесконечный цикл, если браузер вдруг будет закрыт:
private void Application_Exit(object sender, EventArgs e) { ((MainPage)this.RootVisual).Done = true; }
- Запустим приложение и нажмем кнопку "Запуск". Запустятся три потока, которые выполняют методы - счетчики в бесконечном цикле, с различным интервалом времени (100,150,200):
Листинг кода файла MainPage.xaml.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Threading; namespace ThreadsSilverlightApplication { public partial class MainPage : UserControl { private Thread thread1; private Thread thread2; private Thread thread3; private static TextBlock _Thread1TextBlock; private static TextBlock _Thread2TextBlock; private static TextBlock _Thread3TextBlock; private static int c1 = 0; private static int c2 = 0; private static int c3 = 0; private static bool done = true; public bool Done { get { return done; } set { done = value; } } public MainPage() { InitializeComponent(); _Thread1TextBlock = Thread1TextBlock; _Thread2TextBlock = Thread2TextBlock; _Thread3TextBlock = Thread3TextBlock; } public static void DoThread1() { while (!done) { c1++; _Thread1TextBlock.Dispatcher.BeginInvoke(delegate() { _Thread1TextBlock.Text = c1.ToString(); }); Thread.Sleep(100); } } public static void DoThread2() { while (!done) { c2++; _Thread2TextBlock.Dispatcher.BeginInvoke(delegate() { _Thread2TextBlock.Text = c2.ToString(); }); Thread.Sleep(150); } } public static void DoThread3() { while (!done) { c3++; _Thread3TextBlock.Dispatcher.BeginInvoke(delegate() { _Thread3TextBlock.Text = c3.ToString(); }); Thread.Sleep(200); } } private void StartThreads() { done = false; thread1 = new Thread(DoThread1); thread1.Start(); thread2 = new Thread(DoThread2); thread2.Start(); thread3 = new Thread(DoThread3); thread3.Start(); } private void StartButton_Click(object sender, RoutedEventArgs e) { if (false == done) done = true; else StartThreads(); } } }
За основу практического занятия, был взят материал: Mike Snow "Silverlight Tip of the Day #73 - Threading in Silverlight"
< Самостоятельная работа 6 || Самостоятельная работа 7 || Лекция 12 >