c# read file line by line by every button click - c#

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++);

Related

Avoid "file in use by another process" IO exception

The code that I have included below successfully writes to a CSV file. But if the CSV file that I am writing to happens to be open in Excel, I get a System.IO.Exception that indicates that "the file is being used by another process."
How can I change my code so that the program will continuing running and wait until the CSV is no longer open in Excel?
private void timer1_Tick(object sender, EventArgs e)
{
int actmonth, actyear, actsecond;
System.DateTime fecha = System.DateTime.Now;
actmonth = fecha.Month;
actyear = fecha.Year;
if (actmonth <= 9)
{
valorfechaact = System.Convert.ToString(actyear) + "00" + System.Convert.ToString(actmonth);
}
else
{
valorfechaact = System.Convert.ToString(actyear) + "0" + System.Convert.ToString(actmonth);
}
actsecond = fecha.Second;
string label;
label = label1.Text;
string at = "#";
string filename = valorfechaact + ".csv";
string ruta3 = System.IO.Path.Combine(at, label, filename);
if (Directory.Exists(label1.Text))
{
StreamWriter wr = new StreamWriter(ruta3, true);
wr.WriteLine("1asd" + actsecond);
wr.Close();
wr.Dispose();
}
else
{
System.Console.WriteLine("no se puede escribir en el archivo");
timer1.Stop();
}
}
You can write a Methode which try to open the File with a FileStream and return a boolean Flag
A possible Solution is
public static class FileInfoExtension
{
public static bool IsLocked(this FileInfo file)
{
FileStream stream = null;
try
{
stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None);
}
catch (IOException)
{
return true;
}
finally
{
stream?.Close();
}
return false;
}
}
Then you can use it
var fileInfo = new FileInfo(ruta3);
if (!fileInfo.IsLocked())
{
// do code
}
A very simple (and bad) Solution to wait is
while (file.IsLocked())
{
Thread.Sleep(100);
}
General is your Code unclear and difficult to read.
You have much redudant code and few variable are bad named.
Maybe this Guidline can help you https://github.com/dennisdoomen/CSharpGuidelines
Maybe a little bit clearer solution is
private void timer1_Tick(object sender, EventArgs e)
{
var directory = label1.Text;
if (!Directory.Exists(directory))
{
Console.WriteLine("no se puede escribir en el archivo");
timer1.Stop();
return;
}
var now = DateTime.Now;
_valorfechaact = now.Month <= 9 ? $"{now.Year}00{now.Month}" : $"{now.Year}0{now.Month}";
var fullname = Path.Combine("#", directory, $"{_valorfechaact}.csv");
var fileInfo = new FileInfo(fullname);
if (fileInfo.IsLocked())
{
Console.WriteLine($"The File {fullname} is locked!");
return;
}
using (var wr = new StreamWriter(fullname, true))
{
wr.WriteLine("1asd" + now.Second);
}
}
You could take a look at this question:
Checking if an Excel Workbook is open
One of the approaches that are discussed is to simply attempt to access the file. If that throws an exception, you can wait and try again.
If you really want to wait until the workbook is writable you can do that, e.g. by using a while loop (probably you'll want to add a time out, or if relevant alert the user that he/she needs to close the file in Excel).
In code it could be something like:
int someLargeNumberOfIterations = 100000000;
while(FileIsLocked(filepath) && elapsedMs < timeoutMs) {
Thread.SpinWait(someLargeNumberOfIterations);
// Set elapsed
}
// Write the file
where FileIsLocked is a function you write based on the aforementioned post and timeoutMs is some appropriate timeout.

Why does my streamreader and writer suddenly stop working?

Ok, so I'm attempting to create a simple Chat application over TCP/IP for a group of friends of mine who play DnD online. Eventually I want to add more features, but for now I just want the chat to work!!
Here is the code I have for the Main Server
class MainServer
{
IPAddress m_address = IPAddress.Parse("127.0.0.1");
Int32 m_port = 5550;
public static Hashtable userNicknames = new Hashtable(50);
public static Hashtable connectionToNick = new Hashtable(50);
public MainServer()
{
TcpListener listener = new TcpListener(m_address, m_port);
Thread listenThread = new Thread(new ParameterizedThreadStart(StartListening));
listenThread.Start(listener);
Console.WriteLine("Listening for incoming connection requests...");
}
private void StartListening(Object listener)
{
TcpListener server = (TcpListener)listener;
ClientCommCenter commC;
server.Start();
while (true)
{
if (server.Pending())
{
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Client has connected...");
commC = new ClientCommCenter(client);
}
}
}
public static void SendSystemMessage(string msg)
{
StreamWriter writer;
TcpClient[] connectedClients = new TcpClient[MainServer.userNicknames.Count];
MainServer.userNicknames.Values.CopyTo(connectedClients, 0);
for (int ii = 0; ii < connectedClients.Length; ii++)
{
try
{
if (msg.Trim().Equals(String.Empty))
continue;
writer = new StreamWriter(connectedClients[ii].GetStream());
writer.WriteLine("Message from server: " + msg);
writer.Flush();
writer = null;
}
catch (Exception e)
{
MainServer.userNicknames.Remove(MainServer.connectionToNick[connectedClients[ii]]);
MainServer.connectionToNick.Remove(connectedClients[ii]);
}
}
}
public static void SendMessageToAll(string nickname, string msg)
{
StreamWriter writer;
TcpClient[] connectedClients = new TcpClient[MainServer.userNicknames.Count];
MainServer.userNicknames.Values.CopyTo(connectedClients, 0);
for (int ii = 0; ii < connectedClients.Length; ii++)
{
try
{
if (msg.Trim().Equals(String.Empty))
continue;
writer = new StreamWriter(connectedClients[ii].GetStream());
writer.WriteLine(nickname + ": " + msg);
writer.Flush();
writer = null;
}
catch (Exception e)
{
String user = (string)MainServer.connectionToNick[connectedClients[ii]];
SendSystemMessage("ATTENTION: " + user + " has disconnected from chat");
MainServer.userNicknames.Remove(user);
MainServer.connectionToNick.Remove(connectedClients[ii]);
}
}
}
}
Here is the main communication class, used separately by each client
class ClientCommCenter
{
TcpClient m_client;
StreamReader m_reader;
StreamWriter m_writer;
String m_nickname;
public ClientCommCenter(TcpClient client)
{
m_client = client;
Thread chatThread = new Thread(new ThreadStart(StartChat));
chatThread.Start();
}
private String GetNick()
{
m_writer.WriteLine("Enter a nickname to begin.");
m_writer.Flush();
return m_reader.ReadLine();
}
private void StartChat()
{
m_reader = new StreamReader(m_client.GetStream());
m_writer = new StreamWriter(m_client.GetStream());
m_writer.WriteLine("Connected to DnD Chat!!");
m_nickname = GetNick();
while (MainServer.userNicknames.Contains(m_nickname))
{
m_writer.WriteLine("ERROR!!! Username already in use");
m_nickname = GetNick();
}
MainServer.userNicknames.Add(m_nickname, m_client);
MainServer.connectionToNick.Add(m_client, m_nickname);
MainServer.SendSystemMessage("****** " + m_nickname + " ****** has joined the chat!");
m_writer.WriteLine("Now connected....");
m_writer.Flush();
Thread startChatting = new Thread(new ThreadStart(runChat));
startChatting.Start();
}
private void runChat()
{
try
{
String clientMessage = String.Empty;
while(true){
clientMessage = m_reader.ReadLine();
MainServer.SendMessageToAll(m_nickname, clientMessage);
}
}
catch(Exception e)
{
Console.WriteLine(e);
}
}
}
And finally, here is the code for the Client class:
public partial class MainForm : Form
{
[DllImport("kernel32.dll")]
private static extern void ExitProcess(int a);
TcpClient client;
StreamReader m_reader;
StreamWriter m_writer;
public MainForm()
{
InitializeComponent();
}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = false;
Application.Exit();
if (m_reader != null)
{
m_reader.Dispose();
}
ExitProcess(0);
}
private void MainForm_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
SendChat();
}
}
private void SendChat()
{
TextBox txtChat = (TextBox)chatEntry;
if (chatEntry.Lines.Length >= 1)
{
m_writer.WriteLine(txtChat.Text);
m_writer.Flush();
chatEntry.Text = String.Empty;
chatEntry.Lines = null;
}
}
private void RunChat()
{
StreamReader reader = new StreamReader(client.GetStream());
while (true)
{
Application.DoEvents();
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker( delegate{
RunChat();
}));
}
if (reader.Peek() > 0)
{
chatDisplay.AppendText(reader.ReadLine() + "\r\n");
chatDisplay.SelectionStart = chatDisplay.Text.Length;
}
}
}
private void toolstripConnectButton_Click(object sender, EventArgs e)
{
client = new TcpClient("127.0.0.1", 5550);
m_writer = new StreamWriter(client.GetStream());
m_reader = new StreamReader(client.GetStream());
Thread chatThread = new Thread(new ThreadStart(RunChat));
chatThread.Start();
while (true)
{
Application.DoEvents();
}
}
private void sendButton_Click(object sender, EventArgs e)
{
SendChat();
}
}
The problem that I am having with the above code is this: I can connect to the running server perfectly fine, and I am correctly prompted by the server that I have connected, and it then prompts me for a nickname.
I type the nickname into the text box and press send. After this occurs however, I stop receiving messages from the server all together. Literally nothing. I can even spam the connect button and it constantly shows up with the same two messages:
"Connected"
"Enter a nickname"
I have been trying to figure this out for close to 5 hours now, and I simply have no idea what is going on. I have a feeling it is something incredibly simple, as the solution is ALWAYS simple.
So, generous people of SO, can you figure out my problem? Why does my streamreader and streamwriter suddenly stop working?!?!?!
Two things:
First, skip the if (reader.Peek() > 0). Just call reader.ReadLine(); this will block until you have a line available. I am not sure why, but even after sending the message, Peek is returning -1, but ReadLine returns a line at that point, fixing the problem. Anyway, spinning around on Application.DoEvents() is not helping matters.
(Similarly, you can skip if (server.Pending())).
Second, your use of Invoke is faulty; you should not be "Invoking" RunChat() because that is the method that repeatedly polls the stream for new data. This means you will run the entire method on the UI thread, which is precisely what you want to avoid. The UI is busy pumping the Windows message queue. You should "Invoke" only the code that modifies the control's properties.
(I suspect that is why you found it necessary to use Application.DoEvents() anyway. You shouldn't need it if you are handling your threading correctly.)
(Also, the first thing you should do is to check InvokeRequired. As your method is now, you're creating a StreamReader that you can never use. There are other places where you do that, but that's off topic.)
Here are two suggestions:
private void RunChat()
{
StreamReader reader = new StreamReader(client.GetStream());
Delegate invoker = new Action<string>(AppendChatText);
while (true)
Invoke(invoker, reader.ReadLine());
}
or, to use the more classic "invoke" pattern:
private void RunChat()
{
StreamReader reader = new StreamReader(client.GetStream());
while (true)
AppendChatText(reader.ReadLine());
}
private void AppendChatText(string text)
{
if (this.InvokeRequired)
{
this.Invoke((Action<string>)AppendChatText, text);
return;
}
chatDisplay.AppendText(text + "\r\n");
chatDisplay.SelectionStart = chatDisplay.Text.Length;
}
The first has the advantage of creating only one Delegate object; the second creates a new one each time.
Finally, this is a very C# 1.2 approach to the problem. A more up-to-date approach would use async/await to avoid creating all those threads (not to mention System.Collections.Generic.Dictionary<,> instead of HashTable).

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?

Multithreading with checking

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;
}
...

Winforms, Invokes and a problematic button

I am trying to build a chat, basically i used the invoke function what a thread.
I am able to read what the server sends me, but i am able to write only once. i am trying to finish this but not sure how to write to server each time the server:
(take into account that i wrote this before in console application form and the server works fine... i.e. the problem isnt with the server).
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Button btn1 = new Button();
btn1.Click += button1_Click;
}
StreamReader sr;
StreamWriter sw;
TcpClient connection;
private void Form1_Load(object sender, EventArgs e)
{
connection = new TcpClient("127.0.0.1", 5000);
sr = new StreamReader(connection.GetStream());
sw = new StreamWriter(connection.GetStream());
}
private void button2_Click(object sender, EventArgs e)
{
Thread t2 = new Thread(Reader);
t2.Start(connection);
}
string msg;
public void Reader(object o)
{
TcpClient con = o as TcpClient;
if (con == null)
return;
while (true)
{
msg = sr.ReadLine();
Invoke(new Action(Output));
}
}
public void Output()
{
ChatScreen.Text = msg;//set the message on the screen
}
string textinput;
private void button1_Click(object sender, EventArgs e)
{
textinput = InputLine.Text;
sw.WriteLine(textinput);// this thing, writes once, multiple clicks wont send a new line to the server :(..the problem is in this button
sw.Flush();
}
}
what I thought to do is to connect the button so it will be able to do multiple clicks ..e.g btn.Click()..or run a thread with invoke on the WriteLine (but my intuition says that making the button click several times would make the program work
You need to stop the thread process when you close the form, if not when you try to do the invoke, it will fail because the form is disposed and it can't be used to do an invoke. You can override the dispose method to stop the reader thread or you can do it on the onclose method. Or you can check on the reader process if the control it's available (it is not disposed) and if it's not available finish the read process.
You should prevent that the reader process will be launch multiple times too, to prevent errors, so you need to disable the button when the thread is run.
Edited:
You can use something like the following code to read multiple lines and to stop the thread when you close the form.
private bool mbIsRunning = true;
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
lock (this)
{
mbIsRunning= false;
}
}
private bool IsRunning
{
get
{
lock(this)
{
return mbIsRunning;
}
}
}
string msg;
public void Reader(object o)
{
TcpClient con = o as TcpClient;
if (con == null)
return;
while (IsRunning)
{
msg = reader.ReadLine();
string line;
while( (line = reader.ReadLine()) != null )
{
msg = msg + Enviroment.NewLine + line;
}
Invoke(new Action(Output));
}
}
Running up your code, I get a bunch of errors - from the TcpClient throwing an exception and so on.
However, assuming that you haven't posted all of your code, I would recommend putting a try...catch around all of your functions, and then breakpoints in the catch to see what the problem is. Examine the exceptions - exceptions should only be thrown in exceptional circumstances - so your code should really work without doing that.
I do concat on my server code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
TcpListener server = new TcpListener(IPAddress.Any, 5000);
server.Start();
Console.WriteLine("Server started");
string word = "";
savedObject saved = new savedObject();
while (true)
{
TcpClient connection = server.AcceptTcpClient();
Console.WriteLine("connection accepted");
ThreadPool.QueueUserWorkItem(saved.ProssecClient, connection);
}
}
}
}
class savedObject
{
Dictionary<string, StreamWriter> dic = new Dictionary<string, StreamWriter>();
StreamReader[] sr1 = new StreamReader[100];
StreamWriter[] sw1 = new StreamWriter[100];
string[] name = new string[100];
int m;
int a;
int g;
string word;
public string AllWords(string sit)
{
word += sit + " ";// here i concat them
return word;
}
public string word2()
{
return word;
}
public void ProssecClient(object o)
{
TcpClient connection = o as TcpClient;
if (connection == null)
{
return;
}
StreamReader sr = new StreamReader(connection.GetStream());
StreamWriter sw = new StreamWriter(connection.GetStream());
sr1[a++] = new StreamReader(connection.GetStream());
sw1[m++] = new StreamWriter(connection.GetStream());
string word2 = "";
sw.WriteLine("Please, fill your name: ");
name[g++] = sr.ReadLine();
if (name[g] != null && sw1[m] != null)
{
dic.Add(name[g], sw1[m]);
}
try
{
while (true)
{
int i = 0;
word2 = AllWords(sr.ReadLine());
for (i = 0; i < 3; i++)
{
if (sw1[i] != null)
{
sw1[i].WriteLine( name[i] + ": " + word2);// here is the words that are sent..
sw1[i].Flush();
}
}
}
}
catch { Console.WriteLine("client left"); }
}
}

Categories

Resources