I am trying to make a server that will accept clients, and will communicate with them until they say "exit".
the problem is, after 5-8 clients, the server decides that he don't want to accept any more clients, and when a client is connected.. I simply don't see a "client connected : 123.242.123.13:92313" in the console.
anyone knows the problem?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace GatherServer
{
class Program
{
public static int connections = 0, team1 = 0, team2 = 0, playing = 12;
public static string lbleader = "";
public static bool isleader = false;
static TcpListener myList = new TcpListener(IPAddress.Any, 7846);
static void Listeners()
{
string charname = "";
bool inque = false;
Socket socketForClient = myList.AcceptSocket();
if(socketForClient.Connected)
{
Console.WriteLine("Client Connected: " + socketForClient.RemoteEndPoint);
NetworkStream networkStream = new NetworkStream(socketForClient);
StreamWriter streamWriter = new StreamWriter(networkStream);
StreamReader streamReader = new StreamReader(networkStream);
while (true)
{
string newString = streamReader.ReadLine();
if (newString.Contains("#") && inque == false)
{
if (newString.Contains("Leader"))
{
newString = newString.Replace("Leader","");
if (!isleader)
{
isleader = true;
lbleader = newString;
charname = lbleader;
Console.WriteLine(lbleader + " is the gather leader");
}
}
inque = true;
charname = newString;
connections++;
Console.WriteLine("connections: " + connections + " | from: "+charname);
}
if (newString == "exit")
{
if (charname == lbleader)
{
isleader = false;
Console.WriteLine(lbleader + " Left, there is not active leader");
}
else
Console.WriteLine(charname + " has left the game: "+socketForClient.RemoteEndPoint);
if (inque == true)
connections--;
break;
}
else
{
streamWriter.WriteLine(connections.ToString());
streamWriter.Flush();
if (connections == 12)
{
if (!isleader)
{
lbleader = charname;
Console.WriteLine(lbleader + " is the gather leader");
isleader = true;
}
Random rnd = new Random();
int team = rnd.Next(1, 3); // creates a number between 1 and 2
if(team == 1)
{
if (team1 < 6)
{
team1++;
Console.WriteLine(newString + " " + socketForClient.RemoteEndPoint + " assigned to Team 1");
streamWriter.WriteLine("team1"+lbleader);
streamWriter.Flush();
inque = false;
playing--;
break;
}
else
{
Console.WriteLine(newString + " " + socketForClient.RemoteEndPoint + " assigned to Team 2");
team2++;
streamWriter.WriteLine("team2" + lbleader);
streamWriter.Flush();
inque = false;
playing--;
break;
}
}
if(team == 2)
{
if (team2 < 6)
{
Console.WriteLine(newString + " " + socketForClient.RemoteEndPoint + " assigned to Team 2");
team2++;
streamWriter.WriteLine("team2" + lbleader);
streamWriter.Flush();
inque = false;
playing--;
break;
}
else
{
Console.WriteLine(newString + " " + socketForClient.RemoteEndPoint + " assigned to Team 1");
team1++;
streamWriter.WriteLine("team1" + lbleader);
streamWriter.Flush();
inque = false;
playing--;
break;
}
}
}
}
}
if (playing == 0)
{
connections = playing;
playing = 12;
lbleader = null;
isleader = false;
}
Console.WriteLine("playing:" + playing);
Console.WriteLine("connections: " + connections);
inque = false;
streamWriter.Close();
streamReader.Close();
networkStream.Close();
socketForClient.Close();
}
}
static void Main(string[] args)
{
myList.Start();
Console.WriteLine("Sever is up and running...");
for(int i=0; i<1000;i++)
{
Thread newThread = new Thread(new ThreadStart(Listeners));
newThread.Start();
}
}
}
}
Basically, what I want to do is to give each client a thread of its own. but after 5-8 connections, the server Socket socketForClient = myList.AcceptSocket(); not working, I think its because I am running out of threads.. but I have no clue why, there should be 1000 threads open when only 5 to 8 connections are made.
please help!
Found out what was the problem, I was highlighting some stuff in the server console, which caused the server to pause.
Related
I have started a new Console application in .net framework renamed it as ConsoleSpeechProgram and executed but
it is showing me
Exception thrown: 'System.IO.FileNotFoundException' in Microsoft.Speech.dll
Below link I am using for Speech to Text using Microsoft.Speech
https://msdn.microsoft.com/en-us/magazine/dn857362.aspx?f=255&MSPPError=-2147217396
using System;
using Microsoft.Speech.Recognition;
using Microsoft.Speech.Synthesis;
using System.Globalization;
namespace ConsoleSpeech
{
class ConsoleSpeechProgram
{
static SpeechSynthesizer ss = new SpeechSynthesizer();
static SpeechRecognitionEngine sre;
static bool done = false;
static bool speechOn = true;
static void Main(string[] args)
{
try
{
ss.SetOutputToDefaultAudioDevice();
Console.WriteLine("\n(Speaking: I am awake)");
ss.Speak("I am awake");
CultureInfo ci = new CultureInfo("en-us");
sre = new SpeechRecognitionEngine(ci);
sre.SetInputToDefaultAudioDevice();
sre.SpeechRecognized += sre_SpeechRecognized;
Choices ch_StartStopCommands = new Choices();
ch_StartStopCommands.Add("speech on");
ch_StartStopCommands.Add("speech off");
ch_StartStopCommands.Add("klatu barada nikto");
GrammarBuilder gb_StartStop = new GrammarBuilder();
gb_StartStop.Append(ch_StartStopCommands);
Grammar g_StartStop = new Grammar(gb_StartStop);
Choices ch_Numbers = new Choices();
ch_Numbers.Add("1");
ch_Numbers.Add("2");
ch_Numbers.Add("3");
ch_Numbers.Add("4");
GrammarBuilder gb_WhatIsXplusY = new GrammarBuilder();
gb_WhatIsXplusY.Append("What is");
gb_WhatIsXplusY.Append(ch_Numbers);
gb_WhatIsXplusY.Append("plus");
gb_WhatIsXplusY.Append(ch_Numbers);
Grammar g_WhatIsXplusY = new Grammar(gb_WhatIsXplusY);
sre.LoadGrammarAsync(g_StartStop);
sre.LoadGrammarAsync(g_WhatIsXplusY);
sre.RecognizeAsync(RecognizeMode.Multiple);
while (done == false) {; }
Console.WriteLine("\nHit <enter> to close shell\n");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
}
} // Main
static void sre_SpeechRecognized(object sender,
SpeechRecognizedEventArgs e)
{
string txt = e.Result.Text;
float confidence = e.Result.Confidence;
Console.WriteLine("\nRecognized: " + txt);
if (confidence < 0.60) return;
if (txt.IndexOf("speech on") >= 0)
{
Console.WriteLine("Speech is now ON");
speechOn = true;
}
if (txt.IndexOf("speech off") >= 0)
{
Console.WriteLine("Speech is now OFF");
speechOn = false;
}
if (speechOn == false) return;
if (txt.IndexOf("klatu") >= 0 && txt.IndexOf("barada") >= 0)
{
((SpeechRecognitionEngine)sender).RecognizeAsyncCancel();
done = true;
Console.WriteLine("(Speaking: Farewell)");
ss.Speak("Farewell");
}
if (txt.IndexOf("What") >= 0 && txt.IndexOf("plus") >= 0)
{
string[] words = txt.Split(' ');
int num1 = int.Parse(words[2]);
int num2 = int.Parse(words[4]);
int sum = num1 + num2;
Console.WriteLine("(Speaking: " + words[2] + " plus " +
words[4] + " equals " + sum + ")");
ss.SpeakAsync(words[2] + " plus " + words[4] +
" equals " + sum);
}
} // sre_SpeechRecognized
} // Program
} // ns
my problem is that i have a WCF Service and multip
le clients can connect/subscribe to that service and get all Random Data
trough Callback with the service...a Timer starts when a clients subscribed to the service, the thing is that every client then gets all not the same data but thats what i want to achieve...what am i doing wrong?
This is what happens when one client subscribed to the service:
public SubscribeResult Subscribe()
{
SubscribeResult retVal = new SubscribeResult();
try
{
retVal.ClientID = Guid.NewGuid().ToString();
clientID = retVal.ClientID;
ServiceCallback = OperationContext.Current.GetCallbackChannel<ITraceCallback>();
ti = new Timer();
ti.Elapsed += Ti_Elapsed;
ti.Interval = 1000;
ti.Enabled = true;
ti.Start();
retVal.Success = true;
SubscribeClientList.Add(new SubscribeItem {CLIENTID = clientID, SENT = true });
connectedClients += 1;
}
catch (Exception ex)
{
retVal.Success = false;
Console.WriteLine("Something went horribly wrong! \n" + ex.Message);
}
return retVal;
}
And this is what happens when the timer hits zero :
private void Ti_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
if (isSending == false)
{
isSending = true;
// generate message
CreateRandomString crs = new CreateRandomString();
string msg = crs.CreateString(rnd.Next(15, 25));
// increase entry
entry += 1;
// create timestamp of creation
DateTime creation = DateTime.Now;
// generate level
int muchwow = rnd.Next(1, 4);
string lvl = "undefined";
switch (muchwow)
{
case 1:
lvl = "Error";
break;
case 2:
lvl = "Warning";
break;
case 3:
lvl = "Information";
break;
}
bool sucess = ServiceCallback.Message(entry, creation, lvl, msg);
if (sucess == true)
{
CreateRandomString messagePreview = new CreateRandomString();
string prev = messagePreview.TruncString(msg, 20);
Console.WriteLine("[" + DateTime.Now + "] : [" + clientID + "] : " + "'" + prev + "' : " + "(" + lvl + ")");
sucess = false;
}
isSending = false;
}
this is my code
public void ClosePort()
{
if (comPort.IsOpen == true)
{
Thread CloseDown = new Thread(() => CloseSerialOnExit(comPort)); //close port in new thread to avoid hang
CloseDown.Start(); //close port in new thread to avoid hang
}
}
private void CloseSerialOnExit(SerialPort port)
{
port.DiscardOutBuffer();
port.Close();
DisplayData(MessageType.Error, "Port communication has been closed" + " " + DateTime.Now + "\n");
}
why when my app received data close is not work?. is it another solution for this case? my work step is :
Connect port,
Scan and received data,
Disconnect port, and repeat start from connect port again, but when we want to start connect port, system show error message :
access com port is denied.
i thing that happen because the port is not actually close. how to close the port?
this is my code in open port
public bool OpenPort()
{
try
{
//first check if the port is already open
//if its open then close it
if (comPort.IsOpen == true) comPort.Close();
//set the properties of our SerialPort Object
comPort.BaudRate = int.Parse(_baudRate); //BaudRate
comPort.DataBits = int.Parse(_dataBits); //DataBits
comPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), _stopBits); //StopBits
comPort.Parity = (Parity)Enum.Parse(typeof(Parity), _parity); //Parity
comPort.Handshake = (Handshake)Enum.Parse(typeof(Handshake), _parity); //Parity
comPort.PortName = _portName; //PortName
//now open the port
comPort.WriteTimeout = 400;//Write timeout, if the efficiency of the serial driver software, can effectively avoid the deadlock
comPort.ReadTimeout = 400;//Read timeout, ibid
comPort.Open();
comPort.DtrEnable = false;
comPort.RtsEnable = false;
//display message
DisplayData(MessageType.Normal, "Port opened at " + DateTime.Now + "\n");
//return true
return true;
}
catch (Exception ex)
{
DisplayData(MessageType.Error, ex.Message);
return false;
}
}
this is my code in comPort_datareceived
void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//determine the mode the user selected (binary/string)
switch (CurrentTransmissionType)
{
//user chose string
case TransmissionType.Text:
//read data waiting in the buffer
string msg = comPort.ReadExisting();
//display the data to the user
DisplayData(MessageType.Incoming, msg + "\n");
break;
//user chose binary
case TransmissionType.Hex:
//retrieve number of bytes in the buffer
int OpeCode = 0;
int RequestID = 0;
int Product = 0;
int IPenNo = 0;
string status = " ";
while (true)
{
DateTime time = DateTime.Now; // Use current time.
string format = "dddddddd, MMMMM d, yyyy HH:mm:ss";
string currentTime = time.ToString(format);
byte[] TrueData = new byte[256];
try
{
int bytes = comPort.BytesToRead;
if (bytes == 0) continue;
//create a byte array to hold the awaiting data
byte[] comBuffer = new byte[bytes];
comPort.Read(comBuffer, 0, bytes);
DisplayData(MessageType.Incoming, "Hexa :" + ByteToHex(comBuffer) + "\n");
DisplayData(MessageType.Incoming, "Byte :" + bytes.ToString() + "\n");
if (bytes == 3)
{
var lines = File.ReadAllLines(Fullpath).ToList();
// Remove as many lines as you'd like from the end
if (lines.Count > 2)
{
lines.RemoveRange(lines.Count - 2, 2);
}
// Iterate backwards through the list until we've updated 2 (or more or less) lines
var linesUpdated = 0;
for (var i = lines.Count - 1; i >= 0 && linesUpdated < 1; i--)
{
if (lines[i].Contains("OK"))
{
lines[i] = lines[i].Replace("OK", "NG");
linesUpdated++;
}
}
File.WriteAllLines(Fullpath, lines.ToArray());
//DisplayData(MessageType.Incoming, "NG" + "\n");
}
if (bytes == 2)
{
continue;
}
int etx_ok = 0;
for (int i = 0; i < bytes; i++)
{
if (comBuffer[i] == 0x02)
{
//DisplayData(MessageType.Incoming, "cek II:" + checkStatus + "\n");
int length = comBuffer[i + 1];
DisplayData(MessageType.Incoming, "Length=" + length.ToString() + "\n");
if (String.IsNullOrEmpty(bytes.ToString()))
{
status = "NG";
}
if (length + i + 1 != bytes && status == " ")
{
DisplayData(MessageType.Incoming, length.ToString() + " " + i.ToString() + " " + bytes.ToString() + " ");
status = "NG";
DisplayData(MessageType.Incoming, "ERROR \n");
//break;
}
else
{
status = "OK";
}
DisplayData(MessageType.Incoming, "ini statusnya : " + status + "\n");
if (comBuffer[length + i - 1] == 0x03)
{
DisplayData(MessageType.Incoming, "ETX OK\n");
etx_ok = 1;
OpeCode = comBuffer[i + 2];
DisplayData(MessageType.Incoming, "OpeCode=" + OpeCode.ToString() + ",");
RequestID = comBuffer[i + 3];
DisplayData(MessageType.Incoming, "RequestID=" + RequestID.ToString() + ",");
int StoreCode = comBuffer[i + 4];
DisplayData(MessageType.Incoming, "StoreCode=" + StoreCode.ToString() + ",");
int ProductBatteryTraining = comBuffer[i + 5];
DisplayData(MessageType.Incoming, "ProductBatteryTraining=" + ProductBatteryTraining.ToString() + ",");
Product = ProductBatteryTraining >> 4;
DisplayData(MessageType.Incoming, " Product=" + Product.ToString() + ",");
int Battery = ProductBatteryTraining & 4;
DisplayData(MessageType.Incoming, " Batery=" + Battery.ToString() + ",");
int Training = ProductBatteryTraining & 1;
DisplayData(MessageType.Incoming, " Training=" + Training.ToString() + ",");
IPenNo = comBuffer[i + 6];
DisplayData(MessageType.Incoming, "IPenNo=" + IPenNo.ToString() + ",");
int CrcCalc = comBuffer[length + i] + 0x11;
for (int j = 7, k = 0; j < length; j++, k++)
{
//syswrite STDOUT , "TrueDataX " . $length . "\n";
DisplayData(MessageType.Incoming, "TrueDataX " + length.ToString() + "," + "\n");
TrueData[k] = comBuffer[i + j];
}
if (OpeCode == 0x63)
{
byte[] replyStr = new byte[] {
Convert.ToByte(0x45), Convert.ToByte(0x53), Convert.ToByte(0x4c), Convert.ToByte(0x14), Convert.ToByte(0x09), Convert.ToByte(0x00), //#Length Change
Convert.ToByte(0x02), Convert.ToByte(0x08),Convert.ToByte(OpeCode), Convert.ToByte(RequestID),Convert.ToByte(Product-1), Convert.ToByte(IPenNo), //#Reply Header Data
Convert.ToByte(0x00), //#Reply Status
Convert.ToByte(0x03), Convert.ToByte(CrcCalc), //#Footer Data
Convert.ToByte(0xcc), Convert.ToByte(0xcc)
};
comPort.Write(replyStr, 0, replyStr.Length);
//write file to textfile
//string path = #"d:\yosafat\testfile\tes1_Friday0916201614.33.txt";
string IPenID = IPenNo.ToString();
string appendText = ("IPen ID \t" + "Datetime\t\t\t\t\t" + "Status" + Environment.NewLine + IPenID + "\t\t" + currentTime + "\t\t" + status + Environment.NewLine);
File.AppendAllText(Fullpath, appendText);
}
}
else
{
OpeCode = 0;
//syswrite STDOUT , "ETX Bad Data" . $length . "\n";
DisplayData(MessageType.Incoming, "ETX Bad Data" + length.ToString() + "\n");
break;
}
}
if (etx_ok == 1)
{
break;
}
}
}
catch (Exception) { }
}
}
}
public static int GetFirstOccurance(byte byteToFind, byte[] byteArray)
{
return Array.IndexOf(byteArray, byteToFind);
}
Add return inside catch block in SerialPort.DataReceived event handler to quit from while loop in case exception occurred.
while (true)
{
//...
try {
//...
} catch (Exception) { return; //add this}
}
After the other thread Close the port, Exception may occurs when reading data (this line: comPort.Read(comBuffer, 0, bytes);). Without return statement, you will never quit while loop and GC won't dispose SerialPort. Thus, when you try to re-open the port, you will failed.
Why do you call CloseSerialOnExit in a separate thread? Wouldn't it be easier to call it synchronously? Does it really take to much time?
Anyway, if you need it to be like that, you should make sure that the Thread object is not GC'ed before the thread is finished. You should make the CloseDown a member.
You could also use some synchronization to see if the ClosePort has finished at the beginning of OpenPort.
Thread CloseDown = null;
public void ClosePort()
{
if (comPort.IsOpen == true)
{
CloseDown = new Thread(() => CloseSerialOnExit(comPort)); //close port in new thread to avoid hang
CloseDown.Start(); //close port in new thread to avoid hang
}
}
I am using threads to upload images on a FTP. Now I have a problem in limiting the number of threads. when I am creating same number of threads equal to images then it's fine i.e. it is working fine. But now I want to create only suppose maximum of 5 number of threads to upload 100 or more images. I have a datatable in which these 100 images are with a unique field ID which stores suppose 0,1,2,3....and so on for every images. Now I want to start only five threads once so that it may start uploading 5 images parallely. On a Timer, I am checking the status of threads and if I found a thread which is not live now, I want to assign it the 6th Image for uploading and in the same way, if I found other thread which finished its uploading/work, I want to give it 7th image to upload and so on. i.e. this process will run until 100 images are uploaded.
Can you please suggest me a structure by using which I may achieve this? Currently I am creating 100 threads for 100 images and it is working perfect. But I am afraid of creating that much number of threads. Will that affect performance?
My Current Code is:
// A page level variable
Thread [] tr=null;
//On Load of the Control
tr = new Thread[dt.Rows.Count];
//tr = new Thread[MaxID];
for (int i = 0; i < dt.Rows.Count; i++)
//for (int i = 0; i < MaxID; i++)
{
tr[i] = new Thread(new ThreadStart(ProcessItems));
tr[i].Name = Convert.ToString(dt.Rows[i]["Id"]);
tr[i].IsBackground = true;
}
//Start each thread
foreach (Thread x in tr)
{
x.Start();
}
//The method which is used to upload images
public object tLock = new object();
private void ProcessItems()
{
//if (dict.Count == 0)
// pthread.Suspend();
//ArrayList toRemove = new ArrayList();
lock (tLock)
{
try
{
//int NoofAttempts = 0;
//foreach (DictionaryEntry e in dict)
//{
//Thread.Sleep(500);
dr = dt.Select("Is_Uploaded=0 And Id=" + Thread.CurrentThread.Name).FirstOrDefault();
uxImageAndProgress pbCtl = panelControl1.Controls[dr["Image_ID"].ToString()] as uxImageAndProgress;
//NoofAttempts = 0;
string Path = "";
if (ftpPath == "")
{
Path = Global.FTPRemotePath + "/ProductImages/" + dr["Image_ID"] + dr["Extension"].ToString();
}
else
{
Path = ftpPath + dr["Image_ID"] + dr["Extension"].ToString();
}
//object[] loader = e.Value as object[];
int length = (int)(dr["ActualData"] as byte[]).Length;
Stream stream = new MemoryStream(dr["ActualData"] as byte[]);
byte[] rBuffer = ReadToEnd(stream);
int d = length - (int)stream.Length;
d = Math.Min(d, rnd.Next(10) + 1);
if (ftpRequest == null)
{
try
{
#region New Code
ftpRequest = (FtpWebRequest)FtpWebRequest.Create(new Uri(Path));
ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;
ftpRequest.Credentials = new NetworkCredential(Global.FTPLogIn, Global.FTPPassword);
ftpRequest.UsePassive = true;
ftpRequest.UseBinary = true;
ftpRequest.KeepAlive = true;
ftpRequest.Timeout = 20000;
ftpRequest.ContentLength = length;
byte[] buffer = new byte[length > 4097 ? 4097 : length];
int bytes = 0;
int total_bytes = (int)length;
System.IO.Stream rs = ftpRequest.GetRequestStream();
while (total_bytes > 0)
{
bytes = stream.Read(buffer, 0, buffer.Length);
rs.Write(buffer, 0, bytes);
total_bytes = total_bytes - bytes;
}
dr["Is_Uploaded"] = 1;
dt.AcceptChanges();
ftpRequest = null;
pbCtl.Is_Uploaded = true;
rs.Close();
#endregion
}
catch (Exception eeex)
{
ftpRequest = null;
if (ErrorText == "")
ErrorText = eeex.Message.ToString();
else
ErrorText = ErrorText + "," + eeex.Message.ToString();
if (Image_IDsToDelete == "")
Image_IDsToDelete = dr["Image_ID"].ToString();
else
Image_IDsToDelete = Image_IDsToDelete + "," + dr["Image_ID"].ToString();
if (NotUploadedFiles == "")
NotUploadedFiles = Convert.ToString(dr["FileName"]);//dr["Image_ID"] + dr["Extension"].ToString();
else
NotUploadedFiles = NotUploadedFiles + ", " + Convert.ToString(dr["FileName"]);
dr["Is_Uploaded"] = true;
dt.AcceptChanges();
ftpRequest = null;
pbCtl.Is_Uploaded = true;
pbCtl.Is_WithError = true;
}
}
}
catch (Exception ex)
{
XtraMessageBox.Show(ex.Message.ToString(), Global.Header, MessageBoxButtons.OK);
//pthread.Suspend();
}
}
}
//The Timer Event on which I am checking the Status of threads and taking appropriate action
private void timer1_Tick(object sender, EventArgs e)
{
bool Is_AllFinished=true;
//Start each thread
foreach (Thread x in tr)
{
if (x.IsAlive == true)
{
Is_AllFinished = false;
break;
}
else
{
//DataRow[] drs = dt.Select("Is_Uploaded=0");
//if (drs.Count() > 0)
//{
//x. = Convert.ToString(MaxID + 1);
//x.Start();
//MaxID = MaxID + 1;
//}
}
}
if (Is_AllFinished == true)
{
timer1.Enabled = false;
if (Image_IDsToDelete != "")
{
RetailHelper.ExecuteNonQuery("Delete from images where Image_ID in (" + Image_IDsToDelete + ")");
}
if (ErrorText != "")
{
NotUploadedFiles = NotUploadedFiles + ".";
XtraMessageBox.Show("Unable to connect to server. The following files were not uploaded:" + System.Environment.NewLine + NotUploadedFiles + ".", Global.Header, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
Is_Done = true;
}
}
Now, I want to convert this code to use a fixed number of threads. Please help me.
Thanking you!
Use a Semaphore it is good enough. You can polish the code yourself.
const int maxThreads = 5;
Semaphore sm = new Semaphore(maxThreads, maxThreads); // maximum concurrent threads
for (int i = 0; i < dt.Rows.Count; i++)
{
try
{
sm.WaitOne();
Thread tr = new Thread(new ThreadStart(ProcessItems));
tr.Name = Convert.ToString(dt.Rows[i]["Id"]);
tr.IsBackground = true;
tr.Start();
}
finally
{
sm.Release();
}
}
// You don't need the timer anymore
// Wait for the semaphore to be completely released
for (int i=0; i<maxThreads ; i++)
sm.WaitOne();
sm.Release(maxThreads);
if (Image_IDsToDelete != "")
{
RetailHelper.ExecuteNonQuery("Delete from images where Image_ID in (" + Image_IDsToDelete + ")");
}
if (ErrorText != "")
{
NotUploadedFiles = NotUploadedFiles + ".";
XtraMessageBox.Show("Unable to connect to server. The following files were not uploaded:" + System.Environment.NewLine + NotUploadedFiles + ".", Global.Header, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
//The method which is used to upload images
private void ProcessItems()
{
//if (dict.Count == 0)
// pthread.Suspend();
//ArrayList toRemove = new ArrayList();
try
{
sm.WaitOne();
try
{
//int NoofAttempts = 0;
//foreach (DictionaryEntry e in dict)
//{
//Thread.Sleep(500);
dr = dt.Select("Is_Uploaded=0 And Id=" + Thread.CurrentThread.Name).FirstOrDefault();
uxImageAndProgress pbCtl = panelControl1.Controls[dr["Image_ID"].ToString()] as uxImageAndProgress;
//NoofAttempts = 0;
string Path = "";
if (ftpPath == "")
{
Path = Global.FTPRemotePath + "/ProductImages/" + dr["Image_ID"] + dr["Extension"].ToString();
}
else
{
Path = ftpPath + dr["Image_ID"] + dr["Extension"].ToString();
}
//object[] loader = e.Value as object[];
int length = (int)(dr["ActualData"] as byte[]).Length;
Stream stream = new MemoryStream(dr["ActualData"] as byte[]);
byte[] rBuffer = ReadToEnd(stream);
int d = length - (int)stream.Length;
d = Math.Min(d, rnd.Next(10) + 1);
if (ftpRequest == null)
{
try
{
#region New Code
ftpRequest = (FtpWebRequest)FtpWebRequest.Create(new Uri(Path));
ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;
ftpRequest.Credentials = new NetworkCredential(Global.FTPLogIn, Global.FTPPassword);
ftpRequest.UsePassive = true;
ftpRequest.UseBinary = true;
ftpRequest.KeepAlive = true;
ftpRequest.Timeout = 20000;
ftpRequest.ContentLength = length;
byte[] buffer = new byte[length > 4097 ? 4097 : length];
int bytes = 0;
int total_bytes = (int)length;
System.IO.Stream rs = ftpRequest.GetRequestStream();
while (total_bytes > 0)
{
bytes = stream.Read(buffer, 0, buffer.Length);
rs.Write(buffer, 0, bytes);
total_bytes = total_bytes - bytes;
}
dr["Is_Uploaded"] = 1;
dt.AcceptChanges();
ftpRequest = null;
pbCtl.Is_Uploaded = true;
rs.Close();
#endregion
}
catch (Exception eeex)
{
ftpRequest = null;
if (ErrorText == "")
ErrorText = eeex.Message.ToString();
else
ErrorText = ErrorText + "," + eeex.Message.ToString();
if (Image_IDsToDelete == "")
Image_IDsToDelete = dr["Image_ID"].ToString();
else
Image_IDsToDelete = Image_IDsToDelete + "," + dr["Image_ID"].ToString();
if (NotUploadedFiles == "")
NotUploadedFiles = Convert.ToString(dr["FileName"]);//dr["Image_ID"] + dr["Extension"].ToString();
else
NotUploadedFiles = NotUploadedFiles + ", " + Convert.ToString(dr["FileName"]);
dr["Is_Uploaded"] = true;
dt.AcceptChanges();
ftpRequest = null;
pbCtl.Is_Uploaded = true;
pbCtl.Is_WithError = true;
}
}
}
catch (Exception ex)
{
XtraMessageBox.Show(ex.Message.ToString(), Global.Header, MessageBoxButtons.OK);
//pthread.Suspend();
}
}
finally
{
sm.Release();
}
}
It sounds like a producer / consumer queue is the structure you are looking for. Take a look a this answer and the others in the thread for examples of how to employ it.
I have make C# console application which uses timer which connects to MSMQ every 10 seconds get data insert into Oracle database. But the issue is that it log in and log off to domain and create high CPU also create security audit log very much which waste my resources.
My console application runs with task schedule. Code is below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Messaging;
using System.Xml;
using System.IO;
using System.Timers;
using Oracle.DataAccess.Client;
using System.Data;
namespace MSMQ_News
{
class Program
{
private static System.Timers.Timer aTimer;
static void Main(string[] args)
{
try
{
// Create a timer with a ten second interval.
aTimer = new System.Timers.Timer(60000);//10000
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 2 seconds (2000 milliseconds).
//aTimer.Interval = 10000;
aTimer.Enabled = true;
aTimer.Start();
Console.WriteLine("Press the Enter key to exit the program.");
Console.ReadLine();
}
catch (Exception ex)
{
Log(" From Main -- " + ex.Message);
}
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
// Just in case someone wants to inherit your class and lock it as well ...
object _padlock = new object();
try
{
aTimer.Stop();
lock (_padlock)
{
Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
ProcessQueueMsgs();
}
}
catch (Exception ex)
{
Log(" From OnTimedEvent -- " + ex.Message);
}
finally
{
aTimer.Start();
}
}
private static void ProcessQueueMsgs()
{
try
{
while ((DateTime.Now.Hour >= 06)
&& (DateTime.Now.Hour <= 16))
{
DateTime dt = DateTime.Now;
ReceiveNewsDetail(dt);
ReceiveNewsHeader(dt);
}
CloseApp();
}
catch (Exception ex)
{
Log(" From ProcessQueueMsgs -- " + ex.Message);
}
}
static bool QueueExist(string QueueName)
{
try
{
if (MessageQueue.Exists(QueueName))
return true;
else
return false;
}
catch (Exception ex)
{
Log(" From QueueExist -- " + ex.Message);
return false;
}
}
private static void ReceiveNewsHeader(DateTime dt)
{
try
{
MessageQueue mqNewsHeader = null;
string value = "", _tmp = "";
_tmp = "<newsHeader></newsHeader> ";
/*if (QueueExist(#".\q_ws_ampnewsheaderrep"))*/
mqNewsHeader = new MessageQueue(#".\q_ws_ampnewsheaderrep");
int MsgCount = GetMessageCount(mqNewsHeader, #".\q_ws_ampnewsheaderrep");
for (int i = 0; i < MsgCount; i++)
{
Message Msg = mqNewsHeader.Receive();
Msg.Formatter = new ActiveXMessageFormatter();
//need to do this to avoid ??? for arabic characters
using (StreamReader strdr = new StreamReader(Msg.BodyStream, System.Text.Encoding.Default))
{
value = strdr.ReadToEnd();
}
value = value.Replace("\0", String.Empty);
if (value != _tmp)
{
LoadNewsHeader(value, dt);
}
}
}
catch (Exception ex)
{
Log("From ReceiveNewsHeader -- " + ex.Message);
}
}
private static void ReceiveNewsDetail(DateTime dt)
{
try
{
MessageQueue mqNewsDetails = null;
string value = "", _tmp = "";
_tmp = "<news></news> ";
/*if (QueueExist(#".\q_ws_ampnewsrep"))*/
mqNewsDetails = new MessageQueue(#".\q_ws_ampnewsrep");
int MsgCount = GetMessageCount(mqNewsDetails, #".\q_ws_ampnewsrep");
for (int i = 0; i < MsgCount; i++)
{
Message Msg = mqNewsDetails.Receive();
Msg.Formatter = new ActiveXMessageFormatter();
//need to do this to avoid ??? for arabic characters
using (StreamReader strdr = new StreamReader(Msg.BodyStream, System.Text.Encoding.Default))
{
value = strdr.ReadToEnd();
}
value = value.Replace("\0", String.Empty);
if (value != _tmp)
{
LoadNewsDetail(value, dt);
}
}
}
catch (Exception ex)
{
Log("From ReceiveNewsDetail -- " + ex.Message);
}
}
private static void LoadNewsHeader(string text , DateTime dt)
{
try
{
//text = ReplaceSpecialCharacters(text);
//text = Clean(text);
//XmlDocument _xmlDoc = new XmlDocument();
//_xmlDoc.LoadXml(text);
//string fileName = "NewsHeader.xml";
text = text.Replace("<arabicFields>", "<arabicFields>\n\t\t");
//createXMLFile(fileName, text);
XmlDocument _xmlDoc = LoadXMLDoc(text);
string SQL = "";
XmlNodeList newsHeaderList = _xmlDoc.SelectNodes("newsHeader/newsHeaderRep");
if (newsHeaderList.Count > 0)
{
OracleParameter pTRUNCATE = new OracleParameter("P_TABLE_NAME", OracleDbType.Varchar2);
pTRUNCATE.Value = "COMPANIES_NEWS";
DatabaseOperation(CommandType.StoredProcedure, "TRUNCATE_TABLE", pTRUNCATE);
}
foreach (XmlNode news in newsHeaderList)
{
XmlNodeList newsIdList = news.SelectNodes("newsId");
SQL = "Insert into COMPANIES_NEWS(NewsID, NewsID_SEQNO, NEWSSTATUS, LANGUAGE_CD, SEC_CD, RELEASEDATE, RELEASETIME, TITLE, STG_TIME) Values(";
foreach (XmlNode newsId in newsIdList)
{
SQL += "'" + newsId["id"].InnerText + "',";
SQL += "" + newsId["seqNo"].InnerText + ",";
}
SQL += "'" + news["newsStatus"].InnerText + "',";
XmlNodeList newsItemList = news.SelectNodes("newsItem");
foreach (XmlNode newsItem in newsItemList)
{
SQL += "'" + newsItem["languageId"].InnerText + "',";
if (newsItem["reSecCode"] != null)
SQL += "'" + newsItem["reSecCode"].InnerText + "',";
else
SQL += "' ',";
XmlNodeList releaseTimeList = newsItem.SelectNodes("releaseTime");
foreach (XmlNode releaseTime in releaseTimeList)
{
SQL += "TO_DATE('" + releaseTime["date"].InnerText + "','YYYYMMDD'),";
SQL += "" + releaseTime["time"].InnerText + ",";
}
}
XmlNodeList arabicFieldsList = news.SelectNodes("arabicFields");
foreach (XmlNode arabicFields in arabicFieldsList)
{
SQL += "'" + RevertSpecialCharacters(arabicFields["title_AR"].InnerText) + "',";
}
SQL += "TO_DATE('" + dt.ToString() + "','MM/DD/YYYY HH12:MI:SS PM'))";
DatabaseOperation(CommandType.Text, SQL, null);
Console.WriteLine("Header : " + DateTime.Now.ToString());
}
if (SQL != "") //RecordCount("Select Count(*) from COMPANIES_NEWS_DETAILS") > 0
{
OracleParameter pREFRESH = new OracleParameter("P_TABLE_NAMEs", OracleDbType.Varchar2);
pREFRESH.Value = "COMPANIES_NEWS";
DatabaseOperation(CommandType.StoredProcedure, "REFRESH_VW_ALL", pREFRESH);
}
}
catch (Exception ex)
{
Log("From LoadNewsHeader -- " + ex.Message);
}
}
private static void LoadNewsDetail(string text, DateTime dt)
{
try
{
//string fileName = "NewsDetail.xml";
text = text.Replace("<arabicFields>", "<arabicFields>\n\t\t");
//text = createXMLFile(fileName);
//text = text.Replace("<arabicFields>", "<arabicFields>\n\t\t");
XmlDocument _xmlDoc = LoadXMLDoc(text);
string SQL = "";
XmlNodeList newsList = _xmlDoc.SelectNodes("news/newsRep");
if (newsList.Count > 0)
{
OracleParameter pTRUNCATE = new OracleParameter("P_TABLE_NAME", OracleDbType.Varchar2);
pTRUNCATE.Value = "COMPANIES_NEWS_DETAILS";
DatabaseOperation(CommandType.StoredProcedure, "TRUNCATE_TABLE", pTRUNCATE);
}
foreach (XmlNode news in newsList)
{
XmlNodeList newsIdList = news.SelectNodes("newsId");
SQL = "Insert into Companies_news_details(NewsID_ID, NewsID_SEQNO, NewsText_1,NewsText_2,STG_TIME) Values(";
foreach (XmlNode newsId in newsIdList)
{
SQL += "" + newsId["id"].InnerText + ",";
SQL += "" + newsId["seqNo"].InnerText + ",";
}
XmlNodeList arabicFieldsList = news.SelectNodes("arabicFields");
foreach (XmlNode arabicFields in arabicFieldsList)
{
// Log(" Before Arabic Text Data -- :" + arabicFields["newsText_AR"].InnerText);
if (arabicFields["newsText_AR"].InnerText.Length > 4000)
{
SQL += "'" + RevertSpecialCharacters(arabicFields["newsText_AR"].InnerText.Substring(0, 3999)).Replace("\n",Environment.NewLine) + "',";
SQL += "'" + RevertSpecialCharacters(arabicFields["newsText_AR"].InnerText.Substring(3999, arabicFields["newsText_AR"].InnerText.Length)).Replace("\n", Environment.NewLine) + "',";
SQL += "TO_DATE('" + dt.ToString() + "','MM/DD/YYYY HH12:MI:SS PM')";
}
else
{
SQL += "'" + RevertSpecialCharacters(arabicFields["newsText_AR"].InnerText).Replace("\n", Environment.NewLine) + "','',";
SQL += "TO_DATE('" + dt.ToString() + "','MM/DD/YYYY HH12:MI:SS PM')";
}
SQL += ")";
DatabaseOperation(CommandType.Text, SQL, null);
Console.WriteLine("Detail : " + DateTime.Now.ToString());
}
}
if (SQL != "") //RecordCount("Select Count(*) from COMPANIES_NEWS_DETAILS") > 0
{
OracleParameter pREFRESH = new OracleParameter("P_TABLE_NAMEs", OracleDbType.Varchar2);
pREFRESH.Value = "COMPANIES_NEWS_DETAILS";
DatabaseOperation(CommandType.StoredProcedure, "REFRESH_VW_ALL", pREFRESH);
}
}
catch (Exception ex)
{
Log("From LoadNewsDetail -- " + ex.Message);
}
}
private static void CloseApp()
{
System.Environment.Exit(0);
}
protected static int GetMessageCount(MessageQueue q, string queueName)
{
var _messageQueue = new MessageQueue(queueName, QueueAccessMode.Peek);
_messageQueue.Refresh(); //done to get the correct count as sometimes it sends 0
var x = _messageQueue.GetMessageEnumerator2();
int iCount = 0;
while (x.MoveNext())
{
iCount++;
}
return iCount;
}
private static void DatabaseOperation(CommandType cmdType, string SQL, OracleParameter param)
{
string oracleConnectionString = System.Configuration.ConfigurationSettings.AppSettings["OracleConnectionString"];
using (OracleConnection con = new OracleConnection())
{
con.ConnectionString = oracleConnectionString;
con.Open();
OracleCommand command = con.CreateCommand();
command.CommandType = cmdType;
command.CommandText = SQL;
if (param != null)
command.Parameters.Add(param);
command.ExecuteNonQuery();
command.Dispose();
con.Close();
}
}
private static String RevertSpecialCharacters(string pValue)
{
string _retVal = String.Empty;
_retVal = pValue.Replace("'", "''");
return _retVal;
}
public static void Log(string Message)
{
// Create a writer and open the file:
StreamWriter log;
//C:\Software\MSMQ_New_News_Fix
if (!File.Exists(#"C:\MSMQ_New_News_Fix\log.txt"))
{
log = new StreamWriter(#"C:\MSMQ_New_News_Fix\log.txt");
}
else
{
log = File.AppendText(#"C:\MSMQ_New_News_Fix\log.txt");
}
// Write to the file:
log.WriteLine(DateTime.Now.ToString() + " : " + Message);
// Close the stream:
log.Close();
}
public static XmlDocument LoadXMLDoc(string xmlText)
{
XmlDocument doc = new XmlDocument();
try
{
string xmlToLoad = ParseXMLFile(xmlText);
doc.LoadXml(xmlToLoad);
}
catch (Exception ex)
{
Log("From LoadXMLDoc -- " + ex.Message);
}
return doc;
}
private static string ParseXMLFile(string xmlText)
{
StringBuilder formatedXML = new StringBuilder();
try
{
StringReader xmlReader = new StringReader(xmlText);
while (xmlReader.Peek() >= 0)
formatedXML.Append(ReplaceSpecialChars(xmlReader.ReadLine()) + "\n");
}
catch (Exception ex)
{
Log("From ParseXMLFile -- " + ex.Message);
}
return formatedXML.ToString();
}
private static string ReplaceSpecialChars(string xmlData)
{
try
{
//if (xmlData.Contains("objectRef")) return "<objectRef></objectRef>";
int grtrPosAt = xmlData.IndexOf(">");
int closePosAt = xmlData.IndexOf("</");
int lenthToReplace = 0;
if (grtrPosAt > closePosAt) return xmlData;
lenthToReplace = (closePosAt <= 0 && grtrPosAt <= 0) ? xmlData.Length : (closePosAt - grtrPosAt) - 1;
//get the string between xml element. e.g. <ContactName>Hanna Moos</ContactName>,
//you will get 'Hanna Moos'
string data = xmlData.Substring(grtrPosAt + 1, lenthToReplace);
string formattedData = data.Replace("&", "&").Replace("<", "<")
.Replace(">", ">").Replace("'", "'");
if (lenthToReplace > 0) xmlData = xmlData.Replace(data, formattedData);
return xmlData;
}
catch (Exception ex)
{
Log("From ReplaceSpecialChars -- " + ex.Message);
return "";
}
}
}
}
How can i solve above issue
Why not host your queue reader process in a windows service. This will continually poll the queue each 10 seconds.
Then use the windows scheduler to start/stop the service at relevant times to create your service window.
This means you won't need to do anything complicated in your scheduled task, and you won't be loading and unloading all the time.
Well from logic you are very correct that I should make windows service not timer service and Task schedule.
But my question was why It is login / log out frequently, which waste the resource of my Domain server. After intense investigation, I found that calling QueueExits is resource critical. Another thing what I found is that when you connect MSMQ queue you are login to share resource, which will login to Domain. As my code was running every 10-20 seconds it was wasting my Domain server resources.
For resolution, I make my MessageQueue object globally in following way
private static MessageQueue mqNewsHeader = new MessageQueue(#".\q_ws_ampnewsheaderrep");
private static MessageQueue mqNewsDetails = new MessageQueue(#".\q_ws_ampnewsrep");
So it will create Once in the life of the Application and we will log in and log out only once. Then I will pass this object to the function as parameter. I see also that my MessageQueue count function was also resource critical, So I change it to following
protected static int GetMessageCount(MessageQueue q)
{
//var _messageQueue = new MessageQueue(queueName, QueueAccessMode.Peek);
//_messageQueue.Refresh(); //done to get the correct count as sometimes it sends 0
// var x = _messageQueue.GetMessageEnumerator2();
int iCount = q.GetAllMessages().Count();
// while (x.MoveNext())
// {
// iCount++;
// }
return iCount;
}
Hope this clear my answer and will help others also.