Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > Общие вопросы .NET
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 05.03.2013, 14:15   #1
RomanA
Пользователь
 
Регистрация: 10.08.2011
Сообщений: 30
Радость Несколько вопросов по многопоточности

Добрый день.

Сейчас потихоньку осваиваю потоки в C#, и во время изучения возникла небольшая проблема. Написал класс, который создает файл и с определенной перодичностью пишет в него записи. Функция для записи в файл запускается в методе класса, который запускается по таймеру, который стартует сразу после запуска функции Run(). Для запуска этой функции в методе Main создаю отдельный поток, в котором явно прописываю IsBackground = false.

Несколько вопросов:
1)Если правильно понимаю, то свойство IsBackGround должно делать поток основным. Он становится равноправным потоку из которого он запущен, и приложение не должно завершаться до того как завершатся оба потока.

2)Что должен сделать метод Join()? Как понимаю, он приостанавливает выполнение потока для которого вызван. Но как запустить его заново?

Сейчас ситуация такая: если я убираю строку Console.ReadLine(), то приложение завершается сразу после запуска. А мне казалось, что по-первому моему предположению, он должен был работать вечно (т. к. таймер в классе генератора никогда не выключается).

3)У меня есть подозрение, что проблема в таймере... что второй поток только включает таймер и завершается, а сам таймер уже работает в собственном фоновом потоке, который не является основным и поэтому не работает мое первое предположение. Отсюда становится понятным и почему в файл идет запись: таймер работает пока работает основной поток (метод Main) и периодически вызывает метод для записи данных.

4)Если мое последнее предположение верно, то каким образом можно запустить таймер в основном потоке? Или, например, приостановить выполнение основного потока? Тогда получится, что фоновый поток таймера будет выполняться, в то время как основной поток будет приостановлен.

Сейчас, конечно, все работает (до нажатия клавиши), но хочется разобраться что к чему и почему все так.

Буду очень рад, если вы прокомметируете мои гипотезы.

Код:

Код:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
using System.IO;
using System.Threading;

namespace Test32
{
    class Program
    {
        static void Main(string[] args)
        {
            RecordsGenerator rg = new RecordsGenerator("1.txt", 1500);

            Thread th = new Thread(rg.Run);
            th.IsBackground = false;
            th.Start();

            Console.WriteLine("Runned");
            Console.ReadLine();
        }
    }

    class RecordsGenerator
    {
        private string sFileName { get; set; }
        private int nCount { get; set; }
        private int nCurIndex { get; set; }
        private List<string> listRecords;

        public RecordsGenerator(string sFileName = "1.txt", int nCount = 1)
        {
            if (sFileName == "")
                this.sFileName = "1.txt";
            else
                this.sFileName = sFileName;

            if (nCount < 3000)
                this.nCount = nCount;
            else
                this.nCount = 3000;

            listRecords = new List<string>();
            nCurIndex = 0;
        }

        public void Run()
        {
            RunTimer();
        }

        private void RunTimer()
        {
            System.Timers.Timer tm = new System.Timers.Timer();
            tm.Elapsed += new ElapsedEventHandler(this.Generate);
            tm.Interval = 5000;
            tm.AutoReset = true;
            tm.Start();
        }

        private void Generate(object source, ElapsedEventArgs e)
        {
            StreamWriter sw = null;
            try
            {
                sw = new StreamWriter(sFileName, true, Encoding.GetEncoding("utf-16"));
            }
            catch (System.Exception ex)
            {
            	;
            }
            finally
            {
                string sResult = "";
                for (int i = 0; i < nCount; i++)
                {
                    nCurIndex++;
                    sResult += "Record #" + nCurIndex.ToString() + Environment.NewLine;
                }
                listRecords.Add(sResult);
            }

            if (listRecords.Count > 0 && sw != null)
            {
                foreach (string str in listRecords)
                {
                    sw.Write(str);
                }
                listRecords.Clear();
                sw.Close();
            }
        }
    }
}

Последний раз редактировалось RomanA; 05.03.2013 в 14:24.
RomanA вне форума Ответить с цитированием
Старый 05.03.2013, 14:28   #2
Luuzuk
Форумчанин
 
Аватар для Luuzuk
 
Регистрация: 18.01.2012
Сообщений: 975
По умолчанию

Цитата:
Если правильно понимаю, то свойство IsBackGround должно делать поток основным. Он становится равноправным потоку из которого он запущен, и приложение не должно завершаться до того как завершатся оба потока.
IsBackground не делает поток основным. Тем не менее, приложение на самом деле не завершится, пока все НЕ фоновые потоки не завершатся

Цитата:
Что должен сделать метод Join()? Как понимаю, он приостанавливает выполнение потока для которого вызван. Но как запустить его заново?
SomeThread.Join() приостанавливает работу потока, из которого он был вызван (в нашем случае - основного) до тех пор, пока SomeThread не завершится.

-------------------------

По какому условию Ваша программа должна завершить работу вообще?
Благодарить в репутацию. Проклинать — туда же
Luuzuk вне форума Ответить с цитированием
Старый 05.03.2013, 14:33   #3
RomanA
Пользователь
 
Регистрация: 10.08.2011
Сообщений: 30
По умолчанию

На вопрос про приостановку потока метода Main ответ нашел:

Код:
Thread th2 = Thread.CurrentThread;
th2.Join();
Все работает. Но с отальным - по прежнему вопросы.
RomanA вне форума Ответить с цитированием
Старый 05.03.2013, 14:40   #4
Luuzuk
Форумчанин
 
Аватар для Luuzuk
 
Регистрация: 18.01.2012
Сообщений: 975
По умолчанию

3 - верно
4 - while(true) { Thread.Sleep(10);}. Второй поток нафиг не нужен, таймер создавать и запускать прям в Main(). Вместо "true" подставить условие выхода из программы.
Всё
Благодарить в репутацию. Проклинать — туда же
Luuzuk вне форума Ответить с цитированием
Старый 05.03.2013, 14:42   #5
RomanA
Пользователь
 
Регистрация: 10.08.2011
Сообщений: 30
По умолчанию

Цитата:
Сообщение от Luuzuk Посмотреть сообщение
IsBackground не делает поток основным. Тем не менее, приложение на самом деле не завершится, пока все НЕ фоновые потоки не завершатся
При IsBackground = false поток становится не фоновым? И если нет, то как его перевести из фонового в не фоновый?

Цитата:
Сообщение от Luuzuk Посмотреть сообщение
SomeThread.Join() приостанавливает работу потока, из которого он был вызван (в нашем случае - основного) до тех пор, пока SomeThread не завершится.
Т. е. в данном случае поток в котором запущен Main останавливается и ждет пока завершится поток th?

Цитата:
Сообщение от Luuzuk Посмотреть сообщение
По какому условию Ваша программа должна завершить работу вообще?
Нет условия, просто тестирую, ничего осмысленного здесь нет, хочется протестировать и научиться. А вообще, по моему замыслу она должна работать вечно.
RomanA вне форума Ответить с цитированием
Старый 05.03.2013, 14:46   #6
Luuzuk
Форумчанин
 
Аватар для Luuzuk
 
Регистрация: 18.01.2012
Сообщений: 975
По умолчанию

Читайте мой предыдущий пост
Благодарить в репутацию. Проклинать — туда же
Luuzuk вне форума Ответить с цитированием
Старый 05.03.2013, 14:50   #7
RomanA
Пользователь
 
Регистрация: 10.08.2011
Сообщений: 30
По умолчанию

Цитата:
Сообщение от Luuzuk Посмотреть сообщение
Читайте мой предыдущий пост
Спасибо большое за помощь, сейчас стало более понятно!

Потихоньку проясняется в голове.
RomanA вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Несколько вопросов shrek1993 Visual C++ 3 05.08.2012 18:53
Несколько вопросов по C++ Antitime Общие вопросы C/C++ 10 26.01.2012 15:00
Несколько вопросов DeFix Работа с сетью в Delphi 3 28.11.2011 13:48
несколько вопросов spydark91 Общие вопросы Delphi 2 18.07.2011 13:48
БД - Несколько вопросов lutdan БД в Delphi 3 11.10.2009 20:22