Member 11589429 Ответов: 4

Многопоточность в службе windows


Я столкнулся с ситуацией, когда мне нужно создать несколько потоков в службе windows.Вот мой код.Здесь я создал 2 потока.

Я хочу создать один файл Блокнота.Хочу напечатать число от 0 до 2999 с 2 нитками.Он предполагает напечатать какое-то число из потока 1, а затем какое-то число из потока 2 и снова из потока 1, как это.Я не получаю тот же результат. Я делюсь своим кодом и выводом.


Сервисный код :

public partial class FileMultiTasking : ServiceBase
    {
        static System.Timers.Timer timer;
        public static string apppath = System.AppDomain.CurrentDomain.BaseDirectory.ToString();
        public static string errormsg;

        PrintDetails thr1 = new PrintDetails();
        PrintDetails thr2 = new PrintDetails();

        Thread thread1, thread2;

        public FileMultiTasking()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            timer = new System.Timers.Timer();

            timer.Enabled = true;
            timer.Start();

            timer.Interval = 50000;

            timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
           
        }

        void timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            timer.Enabled = true;

            CreateThread();
        }

        private void CreateThread()
        {
            try
            {
                timer.Enabled = false;

         
                 thread1 = new Thread(() => thr1.TextLog("First Thread : Service Started "));
                 thread2 = new Thread(() => thr2.TextLog("Seconf Thread : Service Started"));


                thread1.Name = "Thread 1";
                thread2.Name = "Thread 2";

                thread1.Start();
                thread2.Start();

                timer.Enabled = true;
            }
            catch (Exception ex)
            {
                timer.Enabled = true;
            }
        }


        protected override void OnStop()
        {
            timer.Enabled = false;

            errormsg = "Service Stopped ...............";
                                  
        }
    }



class code : 
<pre> class PrintDetails
    {
        public string apppath = System.AppDomain.CurrentDomain.BaseDirectory.ToString();

        public void TextLog(string msg)
        {
            try
            {
                StreamWriter sw;
                FileInfo f;
                Thread thr = Thread.CurrentThread;
                int j = 0;

             //   string s = apppath + thr.Name + " PrintDetails " + DateTime.Today.ToString("dd-MM-yyyy") + ".txt";

                string s = apppath +  " PrintDetails " + DateTime.Today.ToString("dd-MM-yyyy") + ".txt";

                f = new FileInfo(s);
                if (f.Exists)
                {
                    sw = f.AppendText();
                }
                else
                {
                    sw = f.CreateText();
                    sw.WriteLine();
                }
                sw.WriteLine("-----------------------------------------------------------------");
                sw.WriteLine(msg + "    " + DateTime.Now.ToString("yyyy.MM.dd HH:mm:ss:ffff"));

                if (msg == "Service Stopped ...............")
                {

                }
                else
                {
                    for (int i = 0; i < 3000; i++)
                    {

                        Thread thr2 = Thread.CurrentThread;

                        if (thr2.Name == "Thread 1")
                        {
                            sw.WriteLine(thr2.Name + " : " + i + "    " + DateTime.Now.ToString("yyyy.MM.dd HH:mm:ss:ffff"));
                        }
                        else
                        {
                            sw.WriteLine(thr2.Name + " ::: " + i + "    " + DateTime.Now.ToString("yyyy.MM.dd HH:mm:ss:ffff"));
                        }

                        Console.WriteLine(j);

                        if (j == 0)
                        {
                            j = j + 1;
                            sw.WriteLine("Thread will sleep now -----------------------------------------------------------------");
                            Thread.Sleep(1000);
                        }
                    }
                  
                }
                

                sw.Close();
            }
            catch (Exception e)
            {
                msg = e.Message;
                TextLog(msg);
            }
        }
    }



Выход :

First Thread : Service Started     2018.06.13 12:22:52:8443
Thread 1 : 0    2018.06.13 12:22:52:8443
Thread will sleep now -----------------------------------------------------------------
Thread 1 : 1    2018.06.13 12:22:53:8600
Thread 1 : 2    2018.06.13 12:22:53:8600
Thread 1 : 3    2018.06.13 12:22:53:8600
Thread 1 : 4    2018.06.13 12:22:53:8600
Thread 1 : 5    2018.06.13 12:22:53:8600
Thread 1 : 6    2018.06.13 12:22:53:8600
Thread 1 : 7    2018.06.13 12:22:53:8600
Thread 1 : 8    2018.06.13 12:22:53:8600
Thread 1 : 9    2018.06.13 12:22:53:8600
Thread 1 : 10    2018.06.13 12:22:53:8600
like 2999

The process cannot access the file 'C:\Program Files (x86)\PrintDetails 13-06-2018.txt' because it is being used by another process.    2018.06.13 12:22:53:8912

Thread 2 ::: 0    2018.06.13 12:22:53:8912
Thread will sleep now -----------------------------------------------------------------
Thread 2 ::: 1    2018.06.13 12:22:54:9011
Thread 2 ::: 2    2018.06.13 12:22:54:9011
Thread 2 ::: 3    2018.06.13 12:22:54:9011
Thread 2 ::: 4    2018.06.13 12:22:54:9011
Thread 2 ::: 5    2018.06.13 12:22:54:9011
Thread 2 ::: 6    2018.06.13 12:22:54:9011
Thread 2 ::: 7    2018.06.13 12:22:54:9011
Thread 2 ::: 8    2018.06.13 12:22:54:9011
Thread 2 ::: 9    2018.06.13 12:22:54:9011
Thread 2 ::: 10    2018.06.13 12:22:54:9011
till 2999
//

Why this so?What change shall I do to get output as wanted.


Что я уже пробовал:

Service code : 

<pre>public partial class FileMultiTasking : ServiceBase
    {
        static System.Timers.Timer timer;
        public static string apppath = System.AppDomain.CurrentDomain.BaseDirectory.ToString();
        public static string errormsg;

        PrintDetails thr1 = new PrintDetails();
        PrintDetails thr2 = new PrintDetails();

        Thread thread1, thread2;

        public FileMultiTasking()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            timer = new System.Timers.Timer();

            timer.Enabled = true;
            timer.Start();

            timer.Interval = 50000;

            timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
           
        }

        void timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            timer.Enabled = true;

            CreateThread();
        }

        private void CreateThread()
        {
            try
            {
                timer.Enabled = false;

         
                 thread1 = new Thread(() => thr1.TextLog("First Thread : Service Started "));
                 thread2 = new Thread(() => thr2.TextLog("Seconf Thread : Service Started"));


                thread1.Name = "Thread 1";
                thread2.Name = "Thread 2";

                thread1.Start();
                thread2.Start();

                timer.Enabled = true;
            }
            catch (Exception ex)
            {
                timer.Enabled = true;
            }
        }


        protected override void OnStop()
        {
            timer.Enabled = false;

            errormsg = "Service Stopped ...............";
                                  
        }
    }



class code : 
<pre> class PrintDetails
    {
        public string apppath = System.AppDomain.CurrentDomain.BaseDirectory.ToString();

        public void TextLog(string msg)
        {
            try
            {
                StreamWriter sw;
                FileInfo f;
                Thread thr = Thread.CurrentThread;
                int j = 0;

             //   string s = apppath + thr.Name + " PrintDetails " + DateTime.Today.ToString("dd-MM-yyyy") + ".txt";

                string s = apppath +  " PrintDetails " + DateTime.Today.ToString("dd-MM-yyyy") + ".txt";

                f = new FileInfo(s);
                if (f.Exists)
                {
                    sw = f.AppendText();
                }
                else
                {
                    sw = f.CreateText();
                    sw.WriteLine();
                }
                sw.WriteLine("-----------------------------------------------------------------");
                sw.WriteLine(msg + "    " + DateTime.Now.ToString("yyyy.MM.dd HH:mm:ss:ffff"));

                if (msg == "Service Stopped ...............")
                {

                }
                else
                {
                    for (int i = 0; i < 3000; i++)
                    {

                        Thread thr2 = Thread.CurrentThread;

                        if (thr2.Name == "Thread 1")
                        {
                            sw.WriteLine(thr2.Name + " : " + i + "    " + DateTime.Now.ToString("yyyy.MM.dd HH:mm:ss:ffff"));
                        }
                        else
                        {
                            sw.WriteLine(thr2.Name + " ::: " + i + "    " + DateTime.Now.ToString("yyyy.MM.dd HH:mm:ss:ffff"));
                        }

                        Console.WriteLine(j);

                        if (j == 0)
                        {
                            j = j + 1;
                            sw.WriteLine("Thread will sleep now -----------------------------------------------------------------");
                            Thread.Sleep(1000);
                        }
                    }
                  
                }
                

                sw.Close();
            }
            catch (Exception e)
            {
                msg = e.Message;
                TextLog(msg);
            }
        }
    }

4 Ответов

Рейтинг:
2

RickZeeland

В дополнение к ответу Йохена вас могут заинтересовать Класс readerwriterlockslim что позволяет нескольким потокам находиться в режиме чтения, а одному потоку-в режиме записи с исключительным правом собственности на блокировку.
Смотрите пример здесь: Класс ReaderWriterLockSlim (System.Нарезание резьбы)[^]


Рейтинг:
1

F-ES Sitecore

PrintDetails, похоже, создает файл с его именем, основанным на текущей дате, поэтому использование класса дважды в один и тот же день вызывает конфликт. Вам нужен какой-то способ заставить PrintDetails использовать уникальное имя файла, возможно, также включить идентификатор потока в имя файла. Вы не опубликовали код для класса, поэтому мы не можем дать конкретный совет.


Рейтинг:
0

Jochen Arndt

Вы хотите, чтобы два потока записывались в один и тот же файл?

Тогда вы должны использовать блокировку. То есть каждый поток пытается получить эксклюзивный доступ к общему ресурсу (здесь файл) с помощью соответствующей функции, которая входит в состояние ожидания, пока ресурс не освободится, а затем блокируется. Затем ресурс может быть использован и разблокирован, когда это будет сделано.

Возможным решением для вас (насколько я понимаю ваш код) было бы создание PrintDetails() функция потокобезопасности. То есть каждый критический раздел (здесь: Проверка наличия файла и его создание при необходимости, а также запись в файл) должен быть защищен с помощью блокировок (необязательно как блокировка ReaderWriter), мониторов или мьютексов. Видеть Синхронизация Потоков (C#) | Microsoft Docs[^] для введения по этой теме.


Рейтинг:
0

Gerry Schmitz

Избавиться от всех своих "поток-писатель" код и использовать

File.AppendAllText (path, text)


(или "добавить все строки").

Он более "атомный".

Цитата:
При наличии строки и пути к файлу этот метод открывает указанный файл, добавляет строку в конец файла, а затем закрывает файл. Дескриптор файла гарантированно будет закрыт этим методом, даже если возникнут исключения.

Метод создает файл, если он не существует, но он не создает новые каталоги. Поэтому значение параметра path должно содержать существующие каталоги.