Томский политехнический университет
Опубликован: 23.01.2013 | Доступ: свободный | Студентов: 1157 / 192 | Длительность: 12:09:00
Самостоятельная работа 7:

Создание многопоточного Silverlight - приложения

< Самостоятельная работа 6 || Самостоятельная работа 7 || Лекция 12 >
Аннотация: В рамках данного практического будет создан простой Silverlight проект, выполняющий асинхронно три различных потока.
Ключевые слова: snow, TIP

  1. Создадим Silverlight приложение и назовем его "ThreadsSilverlightApplication":
  2. Разместим четыре элемента на форме (3 TextBlock и 1 Button) как показано на рисунке, и создадим у кнопки соответствующие событие:

    Рис. 18.2.

    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> 
  3. Для того, что бы использовать многопоточность, добавим директиву в начало кода:
    using System.Threading;
  4. Создадим три объекта класса Thread с типом private, как показано в листинге кода:
    public partial class MainPage : UserControl
        {
            private Thread thread1;
            private Thread thread2;
            private Thread thread3;
    …
  5. Далее создадим три объекта класса TextBlock, для того чтобы в дальнейшем свойства ЭУ TexBlock (которые расположены на форме) были доступны в коде:
    private static TextBlock _Thread1TextBlock;
      private static TextBlock _Thread2TextBlock;
      private static TextBlock _Thread3TextBlock;
  6. Создадим три переменных типа int и обнулим их:
    private static int c1 = 0;
     private static int c2 = 0;
     private static int c3 = 0;
  7. Создадим переменную типа bool и присвоим ей значение true, т.к потоки еще не запущены:
    private static bool done = true;
  8. Добавим свойство bool типа public (данное свойство понадобится для пункта 14):
    public bool Done
           {
               get { return done; }
               set { done = value; }
           }
  9. В public MainPage() объектам класса TextBlock присвоим, соответствующим названиям ЭУ TextBlock, значения:
    public MainPage()
            {
                InitializeComponent();
                _Thread1TextBlock = Thread1TextBlock;
                _Thread2TextBlock = Thread2TextBlock;
                _Thread3TextBlock = Thread3TextBlock;
               
            }
  10. Создадим три статичных метода 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)).

  11. Теперь создать метод 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();
         }
  12. Инициируем запуск потоков при нажатии на кнопку:
    private void StartButton_Click(object sender, RoutedEventArgs e)
            {
                if (false == done)
                    done = true;
                else
                    StartThreads();  
          
            }
  13. Перейдем в файл App.xaml.cs. В обработчике события Application_Exit() добавим код, для того, что бы потоки завершили бесконечный цикл, если браузер вдруг будет закрыт:
    private void Application_Exit(object sender, EventArgs e)
      {
          ((MainPage)this.RootVisual).Done = true;  
      }
  14. Запустим приложение и нажмем кнопку "Запуск". Запустятся три потока, которые выполняют методы - счетчики в бесконечном цикле, с различным интервалом времени (100,150,200):

    Рис. 8.3.

    Листинг кода файла 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 >
Владимир Каширин
Владимир Каширин

Вопрос по Курсу: "Параллельное программирование с использованием MS VisualStudia 2010".

При компиляции Самостоятельного задания (одновременная отрисовка прямоугольников, эллипсов и выдача в текст-бокс случайного числа) среда предупреждает: suspend - устаревшая команда; примените monitor, mutex и т.п.

Создаётся впечатление, что Задание создано в более поздней среде, чем VS 2010.