Multithreading with checking - c#

I wanted to write program that will check proxies... I wanted to use mutlithreading but don`t know really how to apply it to my program:
int ktory = 0;
// Button to start multithreading
private void p_check_Click(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++)
{
Thread th = new Thread(test_proxy);
CheckForIllegalCrossThreadCalls = false;
th.Start();
}
}
//This is my function to test proxies
private void test_proxy()
{
try
{
int ile = p_listbox.Items.Count;
string proxy = null;
//'ktory' - means position in listbox
proxy = p_listbox.Items[ktory].ToString();
ktory += 1;
//Splitting on IP and PORT
int gdzie = proxy.IndexOf(":");
string IP = proxy.Remove(gdzie);
string ipp = proxy.Replace(IP + ":", "");
int PORT = Int32.Parse(ipp);
//end o splitting
//My testing of anonimty ( works good don`t need to check)
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(p_proxyjudge.Text);
WebProxy adr_proxy = new WebProxy(IP, PORT);
adr_proxy.UseDefaultCredentials = true;
request.Proxy = adr_proxy;
request.Timeout = 15000;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream stream = response.GetResponseStream();
// Checking if anonymous ( not important)
StreamReader sr = new StreamReader(stream);
while (sr.EndOfStream != true)
{
string checking = sr.ReadLine();
if (!checking.Contains("REMOTE_ADDR ="))
p_work.Items.Add(proxy);
}
sr.Close();
stream.Close();
}
catch (Exception ex)
{
ktory += 1;
}
}
< To code : ile and ktory are just like i, or j as numerous variable >
But my multithreading stops on 10 first proxies or just checks them 10x times as one...
The main problem is to make 10 bots to check proxies and after finished checking one proxy move onto another at listbox (but still others bots work in background)
PLEASE HELP ME :) I`m sitting 2nd day on it and cannot figure it out

You are not locking around access to ktory, which is being altered by multiple threads. Because of this, there is no guarantee that your 10 threads will check 10 different proxies.
Object _lock = new Object();
int ktory=0;
...
private void test_proxy()
{
try
{
int ile = p_listbox.Items.Count;
string proxy = null;
//'ktory' - means position in listbox
lock (_lock) {
proxy = p_listbox.Items[ktory].ToString();
ktory += 1;
}
...

Related

c# read file line by line by every button click

I implemented a server which connects with multiple clients. The server reads a text file and send the first line to the clients and waits 6 seconds and sends the next line and so on. Now I want to send a line only if the button were clicked. How do I do that?
In my button event I put the method in a task because the server has to handle other coming connectivty request from the clients.
Server side:
private void SendFilesButton_Click(object sender, EventArgs e)
{
Task SendTask = Task.Factory.StartNew(() => SendFiles());
}
public void SendFiles()
{
try
{
tcpClient = tcpListener.AcceptTcpClient();
if (tcpClient.Connected)
{
using (StreamReader reader = new StreamReader("C:\\Users\\Chudnofsky\\Desktop\\Projekt\\Neu\\Messwerte.txt"))
{
lock (this)
{
string line;
for (int i = 1; i < 2400; i++)
{
line = reader.ReadLine() + Environment.NewLine;
stream = tcpClient.GetStream();
byte[] toSend = Encoding.ASCII.GetBytes(line);
stream.Write(toSend, 0, toSend.Length);
stream.Flush();
i++;
Thread.Sleep(6000);
}
}
}
}
}
catch (Exception)
{
System.Windows.Forms.MessageBox.Show("Datei konnte nicht gelesen werden!");
}
}
There are 2 simple ways to do this.
If the Messwerte.txt file doesn't change between requests store its contents in a member variable using the File.ReadAllLines method:
private string[] lines = File.ReadAllLines("C:\\Messwerte.txt");
private int nextLine = 0;
Then change this:
line = reader.ReadLine() + Environment.NewLine;
To this:
line = lines[nextLine] + Environment.NewLine;
nextLine++;
Alternatively you dont have to read all lines at once and if the file is growing using the File.ReadLines() method is better suited:
int lineCount = 0;
foreach (var lineInFile in File.ReadLines("C:\\Messwerte.txt"))
{
if (lineCount == nextLine) {
line = lineInFile;
nextLine++;
break;
}
lineCount++;
}
As pointed out by #Slai, here is the ideal way to implement this second method:
line = File.ReadLines("C:\\Messwerte.txt").ElementAtOrDefault(nextLine++);

Socket thread exits after disconnect

I build a quick little script to take data from an app I created for my phone and put it in a textbox and it works perfectly with this code:
private void workerVoid()
{
string receivedDataString = null;
listenSock.Listen(3);
acceptedSock = listenSock.Accept();
listenSock.Bind(new IPEndPoint(IPAddress.Any, 5665));
while(shouldRun)
{
while (listenSock.SendBufferSize != 0)
{
Buffer = new byte[listenSock.SendBufferSize];
int byteCount = acceptedSock.Receive(Buffer);
byte[] byteFormatted = new byte[byteCount];
for (int byteCounter = 0; byteCounter < byteCount; byteCounter++)
{
byteFormatted[byteCounter] = Buffer[byteCounter];
}
receivedDataString = Encoding.ASCII.GetString(byteFormatted);
setTextDelegate sTD = new setTextDelegate(setText);
reqFormVar.Invoke(sTD, new object[] { receivedDataString });
}
}
}
With workerVoid being a thread. Again this works perfectly however, when the device that is connected (my phone) disconnects, the thread stops running altogether (I get the thread .. has exited in visual studio) and my device is unable to connect after that, even though I have a while loop that should run forever.
How can I make it so my device can reconnect again after disconnecting without the thread exiting?
Thanks
Your code might throw an exception , causing the while loop to be ignored, to avoid this .
Surround your internal while loop in a try catch , and move deceleration inside the try catch block like so :
var shouldRun = true;
while(shouldRun)
{
try
{
string receivedDataString = null;
listenSock.Listen(3);
acceptedSock = listenSock.Accept();
listenSock.Bind(new IPEndPoint(IPAddress.Any, 5665));
while (listenSock.SendBufferSize != 0)
{
...
}
}
catch
{
}
}

While loop keeps running after break

I need to download a file and use it to connect to a server. If the connection fails, it restarts the loop. Somehow the while loop keeps running and downloading the file constantly. I think that something weird happens with the boolean Globals.sockRetry but I can't find what's really happening.
public class Globals
{
public static string serverIp;
public static int serverPort;
public static int sockConn = 0;
public static bool sockRetry = false;
public static TcpClient client;
public static NetworkStream nwStream;
public static StreamReader reader;
public static StreamWriter writer;
}
static void connect(Globals g)
{
Globals.sockConn = 1;
try
{
Globals.client = new TcpClient(Globals.serverIp, Globals.serverPort);
Globals.nwStream = Globals.client.GetStream();
Globals.reader = new StreamReader(Globals.nwStream);
Globals.writer = new StreamWriter(Globals.nwStream);
Globals.sockConn = 2;
string inputLine;
while ((inputLine = Globals.reader.ReadLine()) != null)
{
// ParseMessage(Globals.writer, inputLine, g);
}
}
catch
{
Globals.sockRetry = true;
Globals.sockConn = 0;
return;
}
}
static void getInfo()
{
while (true)
{
try
{
WebRequest request = WebRequest.Create(INFO_HOST + INFO_PATH);
WebResponse response = request.GetResponse();
string content;
using (var sr = new StreamReader(response.GetResponseStream()))
{
content = sr.ReadToEnd();
}
string[] contentArray = content.Split(':');
string serverIp = contentArray[0];
string serverPortStr = contentArray[1];
int serverPort = 5000;
Int32.TryParse(serverPortStr, out serverPort);
Globals g = new Globals();
Globals.serverIp = serverIp;
Globals.serverPort = serverPort;
while (Globals.sockConn == 0)
{
if (Globals.sockRetry == false)
{
connect(g);
}
else
{
// error connecting
// wait and retry
Globals.sockRetry = false;
Thread.Sleep(60000);
break;
}
}
continue;
}
catch
{
// error downloading file
// wait and retry
Thread.Sleep(60000);
continue;
}
}
}
The only place there you terminate the loop is here:
if (Globals.sockRetry == false)
{
connect(g);
}
else
{
...
break;
}
So it happens only if Globals.sockRetry == true. Globals.sockRetry is assigned true only if an exception is thrown. If no exception is thrown, the loop never ends.
Change it like this:
if (Globals.sockRetry == false)
{
connect(g);
break;
}
Otherwise after you connect you will connect again, and then again till an exception is thrown (hopefully).
continue continues to the next iteration in the loop.
break stops the loop. So, the loop never ends.
You set sockRetry to false when you want to stop the loop, so you could do this: while (sockRetry)

Multiple asynchronous method calls in a loop Window Phone 7

I have a collection of picture Objects for which I need to download thumbs and pictures files located on dataservise, how can I managed this?
In this method I have loop to call three methods; one to add objects to data base, second to download and save picture thumb and third to download and save picture file the other two is ClientOpenReadCompleted methods.
public bool AddAllPhoto()
{
var amount = App.ViewModel.NewPictures.Count;
for (int i = 0; i < amount; i++)
{
//to add picture to DB
SavePicture(App.ViewModel.NewPictures[i]);
DownloadPicture(NewPictures[i].ID.ToString());
DownloadPictureThumb(NewPictures[i].ID.ToString()));
}
return true;
}
Second;
public void DownloadPictureThumb(string path)
{
string outputString = String.Format("http://" + App.ServerAdress + "/ /Pictures/Thumbs/{0}.jpg", path);
var client = new WebClient();
client.OpenReadCompleted += ClientOpenReadCompleted1;
client.OpenReadAsync(new Uri(outputString));
}
private static void ClientOpenReadCompleted1(object sender, OpenReadCompletedEventArgs e)
{
var resInfo = new StreamResourceInfo(e.Result, null);
var reader = new StreamReader(resInfo.Stream);
byte[] contents;
using (var bReader = new BinaryReader(reader.BaseStream))
{
contents = bReader.ReadBytes((int)reader.BaseStream.Length);
}
var file = IsolatedStorageFile.GetUserStoreForApplication();
var thumbFilePath = String.Format(PicturesThumbsColectionKey + "{0}", PictureDataStoreLocal.ID);
var stream = thumbFile.CreateFile(thumbFilePath);
stream.Write(contents, 0, contents.Length);
stream.Close();
}
And third one
public void DownloadPicture(string path)
{
string outputString = String.Format("http://" + App.ServerAdress + "/Pictures/{0}.jpg", path);
var client = new WebClient();
client.OpenReadCompleted += ClientOpenReadCompleted1;
client.OpenReadAsync(new Uri(outputString));
}
private static void ClientOpenReadCompleted1(object sender, OpenReadCompletedEventArgs e)
{
var resInfo = new StreamResourceInfo(e.Result, null);
var reader = new StreamReader(resInfo.Stream);
byte[] contents;
using (var bReader = new BinaryReader(reader.BaseStream))
{
contents = bReader.ReadBytes((int)reader.BaseStream.Length);
}
var file = IsolatedStorageFile.GetUserStoreForApplication();
IsolatedStorageFileStream stream = file.CreateFile(PictureDataStoreLocal.ID.ToString());
stream.Write(contents, 0, contents.Length);
stream.Close();
}
I assume you want to process the pictures synchronously. If so I would use a wait handle. The easiest way to do this would be to declare a private AutoResetEvent field. The AutoResetEvent is good here because it just lets one thread through and then blocks again automatically.
If you do this you will need to make sure of two things:
1. You do ALL work on a different thread so that when you call WaitOne() you aren't blocking the thread that is supposed to be doing the work.
2. You always reset the wait handle regardless of the outcome of the server calls.
To take care of 1. you just need to update your loop:
m_waitHandle.Reset(); // Make sure the wait handle blocks when WaitOne() is called
for (int i = 0; i < amount; i++)
{
// Process on a background thread
ThreadPool.QueueUserWorkItem((obj) =>
{
// Get the current index. This is an anonymous method so if
// we use 'i' directly we will not necessarily be using the
// correct index. In our case the wait handle avoids this
// problem as the pictures are downloaded one after the other
// but it's still good practise to NEVER use a loop variable in
// an anonymous method.
int index = (int)obj;
//to add picture to DB
SavePicture(App.ViewModel.NewPictures[index]);
DownloadPicture(NewPictures[index].ID.ToString());
DownloadPictureThumb(NewPictures[index].ID.ToString()));
}, i);
m_waitHandle.WaitOne(); // Wait for processing to finish
}
For 2. you need to make sure that m_waitHandle.Set() is ALWAYS called when processing is finished.
What I do is send extra parameters to the OpenReadCompleted event using a delegate like so,
someimage.LoadingCompleted += delegate(object sender, EventArgs imge) { someimage_LoadingCompleted(sender, imge, _item, "someimage"); };
and then in someimage_LoadingCompleted I have code within a switch statement.
Here is my solution, not that elegant but working one; If you have any suggestion to improve , please post and I will edit my post.
EventWaitHandle m_WaitHandle;
public bool AddAllPhoto()
{
var amount = App.ViewModel.NewPictures.Count;
if (m_WaitHandle!=null)
m_WaitHandle.Reset();
for (int i = 0; i < amount; i++)
{
{
SavePicture(App.ViewModel.NewPictures[i]);
ThreadPool.QueueUserWorkItem((obj) =>
{
var index = (int)obj;
DownloadPictureThumb(App.ViewModel.NewPictures[index].ID.ToString());
DownloadPicture(App.ViewModel.NewPictures[index].ID.ToString());
},i);
if (m_WaitHandle != null) m_WaitHandle.WaitOne();
}
return true;
}
public void DownloadPictureThumb(string path)
{
string outputString = String.Format("http://" + App.ServerAdress + "/Pictures/Thumbs/{0}.jpg", path);
var client = new WebClient();
client.OpenReadCompleted += ClientOpenReadCompleted2;
client.OpenReadAsync(new Uri(outputString),path);
}
private static void ClientOpenReadCompleted2(object sender, OpenReadCompletedEventArgs e)
{
var resInfo = new StreamResourceInfo(e.Result, null);
var reader = new StreamReader(resInfo.Stream);
byte[] contents;
using (var bReader = new BinaryReader(reader.BaseStream))
{
contents = bReader.ReadBytes((int)reader.BaseStream.Length);
}
var file = IsolatedStorageFile.GetUserStoreForApplication();
var thumbFilePath = String.Format(PicturesThumbsColectionKey + "{0}", e.UserState as string);
var stream = file.CreateFile(thumbFilePath);
stream.Write(contents, 0, contents.Length);
stream.Close();
}
public void DownloadPicture(string path)
{
string outputString = String.Format("http://" + App.ServerAdress + "/Pictures/{0}.jpg", path);
var client = new WebClient();
client.OpenReadCompleted += ClientOpenReadCompleted1;
client.OpenReadAsync(new Uri(outputString), path);
}
private static void ClientOpenReadCompleted1(object sender, OpenReadCompletedEventArgs e)
{
var resInfo = new StreamResourceInfo(e.Result, null);
var reader = new StreamReader(resInfo.Stream);
byte[] contents;
using (var bReader = new BinaryReader(reader.BaseStream))
{
contents = bReader.ReadBytes((int)reader.BaseStream.Length);
}
var file = IsolatedStorageFile.GetUserStoreForApplication();
var stream = file.CreateFile(e.UserState as string);
stream.Write(contents, 0, contents.Length);
stream.Close();
}
[Here][1] you will find explanation to how to get the url from WebClient in OpenReadCompleted?

Webrequest sudenly stops working

HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(baseurl + url);
req.Timeout = 1000 * 10;
HttpWebResponse response = (HttpWebResponse)req.GetResponse();
Stream str = response.GetResponseStream();
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.Load(str);
response.Close();
string imgurl = doc.DocumentNode.SelectSingleNode("//div[#class='one-page']/a/img[#class='manga-page']").Attributes["src"].Value;
req = (HttpWebRequest)HttpWebRequest.Create(imgurl);
req.Timeout = 1000 * 10;
response = (HttpWebResponse)req.GetResponse();
str = response.GetResponseStream();
Image img = Image.FromStream(str);
response.Close();
return img;
I run this code in a loop (using several threads) to download about 4000 images, and it works brilliantly for the first hundreds but then (at a different point in time for every time I try) it suddenly stops working, and every call to "req.GetResponse()" results in an TimeoutException. I have no idea of why this happen and no idea of what might be wrong or how to deal with it. Any help would be highly appreciated.
The code I use to run this function (it's called GetPage(int) and called as c.GetPage(t)) is as following:
for (int j = 0; j < 2; j++)
{
BackgroundWorker bw = new BackgroundWorker();
num[bw] = j;
bgs.Add(bw);
bw.DoWork += (object sender, DoWorkEventArgs doargs) =>
{
int t = -1;
lock (lockObjForQueueOperations)
{
if (images.Count != 0)
t = images.Dequeue();
}
if(t < 0)
{
doargs.Result = false;
return;
}
currently[sender] = t;
Image img;
try { img = c.GetPage(t); }
catch (Exception e)
{
lock (lockObjForQueueOperations)
{
images.Enqueue(t);
}
lock (Console.Title)
{
if (num[sender] == 0) Console.ForegroundColor = ConsoleColor.Cyan;
else if (num[sender] == 1) Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("**ERR: Error fetshing page {0}, errormsg: {1}", t, e.Message);
Console.ForegroundColor = ConsoleColor.White;
}
doargs.Result = true;
Thread.Sleep(1000*2);
return;
}
lock (Console.Title)
{
if (num[sender] == 0) Console.ForegroundColor = ConsoleColor.Cyan;
else if (num[sender] == 1) Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("\t\tLoaded page {0} of {1}.", t + 1, c.PagesCount);
Console.ForegroundColor = ConsoleColor.White;
}
string imgpath = Path.Combine(ndir, "Page " + (t + 1) + ".png");
img.Save(imgpath, System.Drawing.Imaging.ImageFormat.Png);
img.Dispose();
doargs.Result = true;
};
bw.RunWorkerCompleted += (object sender, RunWorkerCompletedEventArgs runargs) =>
{
if ((bool)runargs.Result) bw.RunWorkerAsync();
else
{
finnishedworkers++;
if (finnishedworkers == 2) restetter.Set();
bw.Dispose();
}
};
bw.RunWorkerAsync();
}
The Timeout property in the HttpWebRequest is in milliseconds. Currently setting it to 10,000 is only 10 seconds, and that might not be enough based off of bandwidth and the size of the data being pulled as well as the complexity of the code being run. I say try increasing that first.
You have a bad design. Instead of creating threads for every request, try calling BeginGetResponse. The framework will handle allocating threads from the threadpool to service your requests.
Add a call to ServicePointManager.SetDefaultConnectionLimit (?) not sure of this to a number like 100.
create a semaphore with a count matching the connection limit count.
In your function that calls BeginGetResponse add a call to semaphore.WaitOne() just before your call get BeginGet...
In your EndGetResponse() handler, call semaphore.Release() to allow the next request to continue.
You are probably exhausting the threadpool with all of your own threads. Monitor your process and see if you can't execute and only use 5-10 threads total, ever. Maybe you could log Thread.Current.ThreadID to see how the SAME thread handles multiple requests.
Done this billions of time. Really.

Categories

Resources