.NET 4.x Снять нагрузку с CPU - C#
Формулировка задачи:
Есть консольное приложение:
Server - класс реализующий асинхронный сокет сервер
Есть класс Api
Вопрос номер 1:
периодически (раз в несколько суток падает Server), без ошибок и тому подобного просто становится недоступен, что в его реализации не так или как отследить его падение? (ps: запросов к нему довольно мало);
Вопрос номер 2:
Просто космическое потребление CPU при 20+ созданных Api классах, каким образом его можно уменьшить?
Если для теста воткнуть такой код, то нагрузка на проц не превышает 4% при 200 классах:
Вопрос номер 3:
как правильно реализовать многопоточное приложение при минимальной нагрузке на проц при том что для каждого класса Api нужен свой таймер и свой отдельный поток выполнения и количество Api классов может достигать 500 шт.
public static Dictionary<string, Api> UserList = new Dictionary<string, Api>();
public static void Main()
{
new Server();
}public class Server
{
public Socket listener = null;
public Server()
{
StartListening();
}
public ManualResetEvent AllDone = new ManualResetEvent(false);
public void StartListening()
{
var localEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 2246);
listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(50);
while (true)
{
AllDone.Reset();
listener.BeginAccept(AcceptCallback, listener);
AllDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
public void AcceptCallback(IAsyncResult ar)
{
AllDone.Set();
var listener = (Socket)ar.AsyncState;
var handler = listener.EndAccept(ar);
var state = new StateObject { WorkSocket = handler };
handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReadCallback, state);
}
public void ReadCallback(IAsyncResult ar)
{
var state = (StateObject)ar.AsyncState;
var handler = state.WorkSocket;
var bytesRead = handler.EndReceive(ar);
if (bytesRead <= 0) return;
state.Sb.Append(Encoding.UTF8.GetString(state.Buffer, 0, bytesRead));
var content = state.Sb.ToString();
try
{
var gh = content.Split(new[] { "\r","\n","\t"," ",":",",","."},StringSplitOptions.RemoveEmptyEntries);
if (gh.Length > 1)
{
content = "OK";
var uid = gh[0];
if (!MainClass.UserList.ContainsKey(uid))
{
MainClass.UserList.Add(uid,new Api(uid, gh[1]));
}
else
{
MainClass.UserList[uid].Dispose();
MainClass.UserList[uid] = new Api(uid, gh[1]);
}
}
else
{
content = "NULL";
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
content = "ERROR";
}
Send(handler, content);
}
void Send(Socket handler, string data)
{
try
{
byte[] byteData = Encoding.UTF8.GetBytes(data);
handler.BeginSend(byteData, 0, byteData.Length, 0, SendCallback, handler);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
void SendCallback(IAsyncResult ar)
{
try
{
var handler = (Socket)ar.AsyncState;
handler.EndSend(ar); //End Async
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
public class StateObject
{
// Client socket.
public Socket WorkSocket;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] Buffer = new byte[BufferSize];
// Received data string.
public StringBuilder Sb = new StringBuilder();
}public class Api:IDisposable
{
public Timer timer = new Timer { Interval = 1000 };
public BackgroundWorker bw = new BackgroundWorker{bw.WorkerSupportsCancellation = true};
public Str5 str5 = new Str5();
public Str4 str4 = new Str4();
public Str3 str3 = new Str3();
public Api(string ww, string qq)
{
str5.ww= ww;
str5.qq = qq;
str4.FlagStart=true;
timer.Elapsed += (a, b) =>
{
str3.GlobalTime++;
if (str3.timeEnd > 0)
{
str3.timeEnd--;
}
...
//еще куча таких же однотипных
};
timer.Start();
bw.RunWorkerCompleted += (a, b) =>
{
MainClass.UserList.Remove(str5.ww);
timer.Stop();
return;
};
bw.DoWork += (a, b) =>
{
while (str4.FlagStart)
{
if (MainClass.Method1(ref str5,ref str4))
{
if (MainClass.Method2(ref str5, ref str3,str4))
{
while (str4.FlagStart)
{
if (str3.Flag1 && str3.EndTime1 <= 0)
{
//производим действия
}
if (str3.Flag2 && str3.EndTime2 <= 0)
{
//производим действия
}
........................................................
//еще десяток таймеров и действий
if (str4.FlagStart) { Thread.Sleep(40000); }
}
}
}
if (str4.FlagStart) { Thread.Sleep(60 * 1000); }
else { break; }
}
str4.FlagStart= false;
MainClass.UserList.Remove(str5.ww);
timer.Stop();
bw.CancelAsync();
return;
};
bw.RunWorkerAsync();
}
public void Dispose()
{
timer.Stop();
timer.Dispose();
bw.CancelAsync();
bw.Dispose();
}
}
public struct Str5
{
//куча паблик полей
}
public struct Str4
{
//куча паблик полей
}
public struct Str3
{
//куча паблик полей
}
public struct Str2
{
//куча паблик полей
}
public struct Str1
{
//куча паблик полей
}
public class Units
{
public string id { get; set; }
...
//куча паблик полей
}bw.DoWork += (a, b) =>
{
while (true)
{
Thread.Sleep(2000);
}
};Решение задачи: «.NET 4.x Снять нагрузку с CPU»
textual
Листинг программы
public static void Main(string[] args)
{
new Api("1");
//new Api("2");
//new Api("3");
//new Api("4");
Console.ReadKey();
}
public static async Task<bool> Task1(Info info)
{
await Task.Delay(1000);
Console.WriteLine(info.Num+" Task1");
info.EndTime = 6;
info.FlagEnd1 = false;
return true;
}
public static async Task<bool> Task2(Info info)
{
await Task.Delay(1000);
Console.WriteLine(info.Num+ " Task2");
info.EndTime2 = 14;
info.FlagEnd2 = false;
return true;
}