13.06.2021, 20:34. Показов 2084. Ответов 4
Здравствуйте.
Необходимо реализовать программу, которая записывает данные в файл пришедшие по UDP со скоростью 1G.
В будущем планируется с 4 розеток принимать данные.
Я написал программу классы прикладываю к вопросу:
Класс UDPHandler принимает данные и возвращает через событие
Класс TOP_file. В нем подписываемся на событие UDPHandler и принимаем данные, после чего отправляем в третий поток эти данные т.е. в класс Writerln_FILE в котором записываем данные.
Так вот, данные принимаются, а когда данные повторно пытаются отправиться в поток в котором происходит запись, вылетает исключение Исключение вида System.Threading.ThreadStateException: Thread is running or terminated; it cannot restart.
at System.Threading.Thread.StartupSetApartm entStateInternal()
at System.Threading.Thread.Start()
at System.Threading.Thread.Start(Object parameter)
Типо поток запущен либо остановлен.
Исключение возникает тут:
| C# |
1
2
3
4
5
6
7
8
9
| private void UDPhandler_DataRecive(byte[] vs)
{
try
{
if(thread_WR.IsAlive) thread_WR.Join();
else thread_WR.Start((object)vs);
}
catch(Exception e) { Console.WriteLine($"Исключение вида {e}"); }
} |
|
Класс TOP_file
| C# |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
| using LookSin;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Threading;
namespace Recive_data_from_ADC
{
class TOP_file
{
/// <summary>
/// Порт для прослушивания
/// </summary>
private static uint NumPort;
public static uint numPort { get { return NumPort; } private set { } }
/// <summary>
/// Путь к катологу для прослушивания
/// </summary>
private static string path_to_catolog_for_file;
public static string Path_to_catolog_for_file { get { return path_to_catolog_for_file; } private set { } }
/// <summary>
/// ip адрес отправителя
/// </summary>
private static IPAddress iPAddress;
public static IPAddress IPAdd_ { get { return iPAddress; } private set { } }
public static UDHHandler UDPhandler;
public static WriterIn_FILE WR_File;
Thread thread_WR;
Thread thread_UDP;
public TOP_file(string path_to_catolog_for_file, IPAddress iPAddress, uint NumPort)
{
////////////////////////////////////////////////////////////////
UDPhandler = new UDHHandler(NumPort, iPAddress);
UDPhandler.DataRecive += UDPhandler_DataRecive;
////////////////////////////////////////////////////////////////
WR_File = new WriterIn_FILE(NumPort, path_to_catolog_for_file);
TOP_file.NumPort = NumPort;
TOP_file.path_to_catolog_for_file = path_to_catolog_for_file;
TOP_file.iPAddress = iPAddress;
///Создаем поток для работы с записью в файл
thread_WR = new Thread(new ParameterizedThreadStart(WR_File.WriterInFILE));
///Создаем поток для работы с UDP
thread_UDP = new Thread(new ThreadStart(UDPhandler.UDPRecive));
}
private void UDPhandler_DataRecive(byte[] vs)
{
try
{
if(thread_WR.IsAlive) thread_WR.Join();
else thread_WR.Start((object)vs);
}
catch(Exception e) { Console.WriteLine($"Исключение вида {e}"); }
}
public void StartRecive()
{
thread_UDP.Start();
}
/// <summary>
/// Метод полностью завершает выполнение потоков приема и записи данных
/// </summary>
public void Stop()
{
UDPhandler.UDPClose();
thread_WR.Abort();
thread_WR.Join();
thread_UDP.Abort();
thread_UDP.Join();
}
}
} |
|
Класс WriterIn_FILE
| C# |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
| using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace Recive_data_from_ADC
{
/// <summary>
/// Класс для записи данных в бинарный файл
/// </summary>
public class WriterIn_FILE
{
/// <summary>
/// Делегат для события которое говорит об возникших проблемах или исключении
/// </summary>
/// <param name="str"></param>
public delegate void DelegateForString(string str);
/// <summary>
/// Событие возвращающее сообщение
/// </summary>
public event DelegateForString Message;
/// <summary>
/// Событие возвращающее возникшее исклчение
/// </summary>
public static event DelegateForString Exep_;
/// <summary>
/// Начальное имя файл, изменяет в тот момент когда в предыдущем файле размер превысил 1 Гбайт
/// </summary>
public string Start_Name_file { get; private set; }
/// <summary>
/// Приемный порт, в данном классе выступает в роле идентефикатора для файла, в который пишутся данные с определенного порта
/// По желанию можно любое число от 0 до 4294967295
/// </summary>
public uint receiving_port { get; private set; }
/// <summary>
/// Путь к катологу где лежит файл
/// </summary>
public string path_to_catolog_for_file { get; private set; }
/// <summary>
/// Конструктор класса
/// </summary>
/// <param name="receiving_port">Приемный порт, в данном классе выступает в роле идентефикатора для файла, в который пишутся данные с определенного порта
/// По желанию можно любое число от 0 до 4294967295</param>
/// <param name="path_to_catolog_for_file">Путь к катологу где лежит файл</param>
public WriterIn_FILE(uint receiving_port, string path_to_catolog_for_file)
{
//Создаем экземпляр класса для проверки наличия данной директории
System.IO.DirectoryInfo dirInfo = new System.IO.DirectoryInfo(path_to_catolog_for_file);
//Проверяем существует ли такая директория
//Если нет, то создаем ее, если она существует создаем файл согодняшних измерений
if (!dirInfo.Exists)
{
Console.WriteLine("Директория не существует, и будет создана");
//Message?.Invoke("Директория не существует, и будет создана");
try
{
dirInfo.Create();
Console.WriteLine("Директория cоздана");
//Message?.Invoke("Директория cоздана");
}
catch (Exception e)
{
Console.WriteLine($"Возникло исключение вида {e}");
//Exep_?.Invoke($"Возникло исключение вида {e}");
}
}
///Создаем начальное имя файла из даты, времени и года плюс порт просушиввания
///Имя файла будет изменяться со врменем когда размер файла будет превышать 1Гбайт, будет
///создаваться новый файл с дополнительным префиксом _1,_2...
string dateTime = DateTime.Now.ToString();
dateTime = dateTime.Replace(":", ".");
Start_Name_file = dateTime + $" Порт прослушивания {receiving_port}.txt";
this.receiving_port = receiving_port;
this.path_to_catolog_for_file = path_to_catolog_for_file;
//Создаем папку в директории для записи измерений производимых сегодня.
try
{
using (File.Create($@"{path_to_catolog_for_file}\{Start_Name_file}")) { }
Console.WriteLine("Файл создан");
//Message?.Invoke("Файл создан");
}
catch(Exception e)
{
Console.WriteLine($"Возникло исключение вида {e}");
//Exep_?.Invoke($"Возникло исключение вида {e}");
}
}
/// <summary>
/// Счетчик файлов
/// </summary>
private static int count;
public static int Count_file { get { return count; } private set { count = 1; } }
/// <summary>
/// Метод для записи данных в файл, также производит проверку файла и если рамер файла превышает 1гбайт, создает новый файл с префиксом _2
/// </summary>
/// <param name="date">Данные, типо object был выдран для того, чтобы можно было передавать данные в поток</param>
public void WriterInFILE(object date)
{
byte[] vs = (byte[])date;
try
{
//Проверяем длину файла
//Запись в файл будем осуществлять по 1 Гбайту
FileInfo fileInfo = new FileInfo($@"{path_to_catolog_for_file}\{Start_Name_file}");
if(fileInfo.Length != 1073741824)
{
//Если файл размером меньше чем 1 Гбайт, то записываем данные
using(FileStream fileStream = new FileStream($@"{path_to_catolog_for_file}\{Start_Name_file}", FileMode.OpenOrCreate))
{
fileStream.Write(vs);
}
}
else
{
count++;
//Если длина файла превысила размер 1 Гбайт, то создаем новый файл с префиксом 2
//Переписываем переменную Start_Name_file и начинаем запись
File.Create($@"{path_to_catolog_for_file}\{Start_Name_file}_{count}");
Start_Name_file = @$"{Start_Name_file}_{count}";
using (FileStream fileStream = new FileStream($@"{path_to_catolog_for_file}\{Start_Name_file}", FileMode.OpenOrCreate))
{
fileStream.Write(vs);
}
}
}
catch (Exception e)
{
Console.WriteLine($"Возникло исключение вида {e}\r\n");
//Exep_?.Invoke($"Возникло исключение вида {e}\r\n" +
//$"Возможные ошибки:\r\n" +
//$"-Файл был удален\r\n" +
//$"-Запись в файл невозможна\r\n" +
//$"-Возникло исключение при создании файла");
}
}
}
} |
|
Класс UDHHandler
| C# |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
| using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace LookSin
{
class UDHHandler
{
private bool FlagStorResive = false;
/// <summary>
/// Делегат для события возвращаюего полученные данные из UDP
/// </summary>
/// <param name="vs"></param>
public delegate void UDHHandDelegat(byte[] vs);
/// <summary>
/// Делегат для создания события, которое возвращает исключения
/// </summary>
public event UDHHandDelegat DataRecive;
/// <summary>
/// Событие возвращающее исключение
/// </summary>
/// <param name="str"></param>
public delegate void UDPHandlerExeption(string str);
/// <summary>
/// Событие возвращающее принятые данные
/// </summary>
public event UDPHandlerExeption Exep;
/// <summary>
/// Номер порта прослушивания
/// </summary>
public UInt16 NumPort { get; private set; }
/// <summary>
/// ip адрес отправителя
/// </summary>
public IPAddress iPAddres { get; private set; }
private UdpClient udpClient;
private IPEndPoint RemoteIpEndPoint = null;
/// <summary>
/// Конструктор класса
/// </summary>
/// <param name="NumPort">Принимает прослушиваемый порт</param>
/// <param name="iPAddres">ip адрес отправителя</param>
public UDHHandler(uint NumPort, IPAddress iPAddres)
{
this.iPAddres = iPAddres;
this.NumPort = (ushort)NumPort;
udpClient = new UdpClient((ushort)NumPort);
RemoteIpEndPoint = new IPEndPoint(iPAddres, (ushort)NumPort);
}
public void UDPRecive()
{
try
{
while (FlagStorResive == false)
{
byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint);
Console.WriteLine(receiveBytes.ToString());
DataRecive?.Invoke(receiveBytes);
}
}
catch(Exception e)
{
Console.WriteLine($"Произошло исключение в блоке UDPRecive, вида {e} ");
//Exep?.Invoke($"Произошло исключение в блоке UDPRecive, вида {e} \r\n" +
// $"----> Метод приема закрыт, для возобновления необходимо вызвать заново метод UDPRecive();");
return;
}
}
public void UDPClose()
{
FlagStorResive = true;
udpClient.Close();
}
}
} |
|
Класс Program
| C# |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
| using LookSin;
using System;
using System.Collections.Generic;
using System.Net;
using System.Runtime.InteropServices;
namespace Recive_data_from_ADC
{
class Program
{
static bool exitSystem = false;
static TOP_file tOP_File_2;
static TOP_file tOP_File;
#region Trap application termination
[DllImport("Kernel32")]
private static extern bool SetConsoleCtrlHandler(EventHandler handler, bool add);
private delegate bool EventHandler(CtrlType sig);
static EventHandler _handler;
enum CtrlType
{
CTRL_C_EVENT = 0,
CTRL_BREAK_EVENT = 1,
CTRL_CLOSE_EVENT = 2,
CTRL_LOGOFF_EVENT = 5,
CTRL_SHUTDOWN_EVENT = 6
}
private static bool Handler(CtrlType sig)
{
Console.WriteLine("Exiting system due to external CTRL-C, or process kill, or shutdown");
////do your cleanup here
//System.Threading.Thread.Sleep(5000); //simulate some cleanup delay
//Console.WriteLine("Cleanup complete");
////allow main to run off
//exitSystem = true;
////shutdown right away so there are no lingering threads
Environment.Exit(-1);
return true;
}
#endregion
static void Main(string[] args)
{
// Some biolerplate to react to close window event, CTRL-C, kill, etc
_handler += new EventHandler(Handler);
SetConsoleCtrlHandler(_handler, true);
byte[] ip = {192,168,0,57};
IPAddress iPAddres = new IPAddress(ip);
tOP_File = new TOP_file($@"C:\Users\Nikita\Desktop\LOL", iPAddres, 1400);
Console.WriteLine("Запись с порта 1400 начата");
tOP_File.StartRecive();
tOP_File_2 = new TOP_file($@"C:\Users\Nikita\Desktop\LOL", iPAddres, 2500);
tOP_File_2.StartRecive();
Console.WriteLine("Запись с порта 2500 начата");
}
}
} |
|
Большое спасибо за помощь!!!!
Добавлено через 1 час 23 минуты

Сообщение от NiKit_A
Исключение возникает тут:
private void UDPhandler_DataRecive(byte[] vs)
{
try
{
if(thread_WR.IsAlive) thread_WR.Join();
else thread_WR.Start((object)vs);
}
catch(Exception e) { Console.WriteLine($"Исключение вида {e}"); }
}
|
Я понял почему возникает исключение, потому что поток отработал свое в классе WriterIn_FILE метод WriterInFILE.
Тогда как можно поступить, чтобы запись осуществлялась постоянно? Точнее данные пришли, после этого передались во второй поток (в это время данные идет и иду) который начал запись и все по кругу.