I have a method that sends a message to a client as seen below. But if I call this method twice once after another it won't work properly and the data seems to have never been sent at all.
I added some comments below to show the issue.
public static void SendRequestInformation(Client target, int messageId)
{
NetworkStream stream = target.getClientSocket().GetStream();
byte[] byteData = null;
switch (messageId)
{
case 0:
byteData = Encoding.ASCII.GetBytes("ping");
break;
case 1:
byteData = Encoding.ASCII.GetBytes("handshake");
break;
case 3:
byteData = Encoding.ASCII.GetBytes("osif");
break;
case 4:
byteData = Encoding.ASCII.GetBytes("idle");
break;
}
try
{
stream.Write(byteData, 0, byteData.Length);
stream.Flush();
}
catch (Exception e)
{
ClientHandle.RemoveFromClientPool(target, "Unable to reach Client");
}
}
// so if here I have a method like...
private void onRefreshMenuClick(object sender, RoutedEventArgs e)
{
MenuItem mi = sender as MenuItem;
if (mi != null)
{
ContextMenu cm = mi.CommandParameter as ContextMenu;
if (cm != null)
{
Grid g = cm.PlacementTarget as Grid;
if (g != null)
{
var p = Mouse.GetPosition(g);
int row = 0;
int col = 0;
double accumulatedHeight = 0.0;
double accumulatedWidth = 0.0;
// calc row mouse was over
foreach (var rowDefinition in g.RowDefinitions)
{
accumulatedHeight += rowDefinition.ActualHeight;
if (accumulatedHeight >= p.Y)
break;
row++;
}
Client c = getRowClient(row);
if (c != null)
{
//the below two lines seem to not be called if called only the top one seems to work
ConnectionHandle.SendRequestInformation(c, 1);
ConnectionHandle.SendRequestInformation(c, 4);
}
else
if (debugWindow != null)
debugWindow.LogTextBox.AppendText("Unable to find client!");
}
}
}
}
Related
I've made a small tool bar that sits in a transparent form, it loads a variable sized menu from a text file and can be changed on the fly. Each button is a type of Label, the bar is just a list of buttons and adds/removes them in the correct spots. Width of the form is only a little bigger than the menu bar so that sub menu isn't cut off
Everything is working sweet except, when I reload everything part of the toolbar is lost. I've attempted to change the width so many ways, I've cleared and removed the controls from the form, refreshing the form/menu, updating it etc however nothing seems to make it work as intended EXCEPT if I call the reload function twice in a row, it works. I can't see why calling it once doesn't work but calling it twice works.
I'm fine with calling reload twice in a row as it would only be called a couple times a week.
Question: what on earth is causing this?
photo of issues first photo shows what it should look like, second is after removing a menu button and reloading, third is after adding a button and reloading
//calling this.reload() doesn't work
//calling this.reload();this.reload() works
void reload(Object o = null, EventArgs e = null)
{
this._menuBar.clear();
this.loadFromFile();
}
void loadFromFile(Object o = null, EventArgs e = null)
{
try
{
if (File.Exists("kpi.txt"))
{
string cline = "", cmenu = "", lhs = "";
menuList mb = null;
StreamReader sr = new StreamReader("kpi.txt");
while (!sr.EndOfStream)
{
cline = sr.ReadLine(); //get current line
if (cline.Length > 0 && cline[0] != ';')
{
//check if main menu/command
if (cline[0] == '[')
{
cmenu = Regex.Match(cline, #"(?<=^\[)[a-zA-Z -\#_{-~\^\r\n]+(?=\])").Value;
if (cmenu != "")
{
mb = this._menuBar.addMenuButton(cmenu);
mb.data["options"] = Regex.Match(cline, #"\/\w+$").Value;
var match = Regex.Match(cline, #"(?<=<)([^>\[\]\r\n]+)(?=>)");
mb.data["count"] = (match.Success ? match.Value : "0");
mb.data["copy"] = "";
applyMenuOptions(mb, false);
}
}
//just a standard line
else
{
cline = cline.Trim();
lhs = Regex.Match(cline, #"^[^\;\<\[\]\r\n]+(?=$|\<|\;)").Value;
if (mb.getSubMenuItem(lhs) == null)
{
var newButton = mb.addSubMenu(lhs);
if (newButton != null)
{
newButton.parent = mb;
newButton.data["options"] = mb.data["options"];
newButton.data["copy"] = Regex.Match(cline, #"((?<=\;)[^\[\]\<\r\n]+(?=<|$))").Value;
var matches = Regex.Match(cline, #"(?<=<)([^>\[\]\r\n]+)(?=>)");
int intout = 0;
if (int.TryParse(matches.Value, out intout))
{//no description
newButton.data["description"] = "";
newButton.data["count"] = intout.ToString();
}
else
{
newButton.data["description"] = matches.Value;
newButton.data["count"] = (matches.NextMatch().Success ? matches.NextMatch().Value : "0");
}
applyMenuOptions(newButton);
newButton.addMiddleClick(this.addcopy);
if (newButton.data["options"].Contains("i"))
{
newButton.addRightClick(this.appendInfo);
newButton.addRightClick(this.increment);
}
}
}
}
}
}
sr.Close();
this._menuBar.squish();
this.Width = this._menuBar.Width+50;
}
else
{
menuList mb = this._menuBar.addMenuButton("menu");
mb.data["options"] = "\\m";
mb.data["count"] = "0";
mb.data["copy"] = "";
mb.data["description"] = "";
applyMenuOptions(mb, false);
saveDictonary();
}
}
catch (Exception ex)
{
MessageBox.Show("Failed to load data " + ex);
//ILog log = LogManager.GetLogger(typeof(Program));
//log.Info(ex);
}
}
public menuList addMenuButton(string s, int w = 0, int h = 0, int x = -1, int y = -1)
{
menuList mb = new menuList(this._form, s);
if (this.menuItems.Exists(z => z.Text == s)) return null;
mb.Width = (w==0?settings.intOf("ButtonWidth"):w);
mb.Height = (h==0?settings.IntOf("ButtonHeight"):h);
if (x == -1 || y == -1)
mb.Location = new Point(this.menuItems.Count > 0 ? this.menuItems.Last().Location.X + this.menuItems.Last().Width : padding);
else mb.Location = new Point(x, y);
mb.BringToFront();
mb.Show();
this.menuItems.Add(mb);
// this.Refresh();
return mb;
}
internal void clear()
{
foreach(var i in this.menuItems)
{
this._form.Controls.Remove(i);
i.clear();
i.Dispose();
}
this.menuItems.Clear();
this._form.Controls.Remove(this);
this.menuItems = new List<menuList>();
this._form.Controls.Add(this);
}
internal void squish()
{
try
{
this.Width = (this.menuItems.Count * this.menuItems.First().Width) + (2 * padding);
}
catch(Exception ex) { MessageBox.Show(""+ex); }
}
Found the culprit, bother the button class and the tool bar class were both adding themselves to the form control instead of button class adding to the tool bar (picture box) controls!
Removing transparency showed the buttons not moving when the tool bar was moved!
Together with a friend, we are trying to create a sea battle for playing on a local network, we made a field of buttons, created islands on it, you can set up ships and move them. But when we connected the form to our server, after requesting the package, the form stops drawing buttons, they store the correct data, but their visual update does not occur
Here are the pieces of code
private void button1_Click(object sender, EventArgs e)
{
comboBox1.Visible = false;
comboBox2.Visible = false;
button1.Visible = false;
comboBox3.Visible = false;
button2.Visible = true;
SendPacket(PacketInfo.SendGameInfo);
Thread thread = new Thread(FightIsDone);
thread.Start();
State = GameState.Waiting;
}
void FightIsDone()
{
ReceivePacket();
this.Invoke(new Action(() => GameUpdate()));
}
public void GameUpdate()
{
Console.WriteLine("!");
State = GameState.Planing;
foreach (Ship ship in Ships)
{
ship.UseModuls();
}
SetShip(Ships);
UpdateSight();
Draw();
}
The problem is here, this method changes the image of the button or its color, it works fine until the packet is sent to the server, but after receiving it, only the information is updated, and the appearance of the form does not change
public void Draw()
{
foreach (CellButton Butt in Field)
{
if (Butt.Sigth)
{
Butt.Image = null;
SetImage(Butt);
}
else
{
Butt.BackColor = Color.Gray;
Butt.Image = null;
}
}
}
public void SetImage(CellButton Butt)
{
switch (Butt.Entety)
{
case GameObject.Water: Butt.BackColor = Color.DodgerBlue; break;
case GameObject.Island: Butt.Image = GetObjectImage(GameObject.Island); break;
case GameObject.Ship:
{
Butt.Image = Butt.modul.ModulImage;
break;
}
case GameObject.Torpedo: Butt.BackColor = Color.DarkBlue; break;
case GameObject.Fire: Butt.Image = GetObjectImage(GameObject.Fire); break;
}
}
static void SendPacket(PacketInfo info)
{
ms.Position = 0;
switch (info)
{
case PacketInfo.Connect:
writer.Write(0);
break;
case PacketInfo.SendCoordinate:
writer.Write(1);
formatter.Serialize(ms, new Coordinate(5, 0));
break;
case PacketInfo.LaunchSearch:
writer.Write(2);
writer.Write(Me.ID);
break;
case PacketInfo.SendGameInfo:
writer.Write(3);
writer.Write(Me.ID);
List<Ship> shpooks = new List<Ship>();
foreach (Ship s in Ships)
if (s.PlayerID == Me.ID) shpooks.Add(s);
formatter.Serialize(ms, shpooks);
break;
}
socket.Send(ms.GetBuffer());
}
static int ReceivePacket()
{
ms.Position = 0;
socket.Receive(ms.GetBuffer());
int code = reader.ReadInt32();
switch (code)
{
case 0:
{
Console.WriteLine("Catch");
Console.WriteLine(ms.ToString());
bool IsConected = reader.ReadBoolean();
if (IsConected)
{
Me.ID = reader.ReadInt32();
return 1;
}
break;
}
case 2:
{
return 1;
break;
}
case 3:
{
Cell[,] cells = (Cell[,])formatter.Deserialize(ms);
for (int i = 0; i < Width; i++)
for (int j = 0; j < Hight; j++)
{
Field[i, j] = new CellButton(new Coordinate(i, j));
Field[i, j].SetCell(cells[i, j]);
}
Ships.Clear();
Ships.AddRange((List<Ship>)formatter.Deserialize(ms));
break;
}
}
return -1;
}
This is the form before calling Draw():
This is how the form looks after calling Draw():
And so, after a request to the server and method Draw():
I spent a lot of time finding solutions, methods like Form.Update() and Form.Refresh() don't help
I'm trying to make a little software in which I could modify a pre-existing xml file. I would have the chance to add some values (via usercontrols) to the alphabet letters, and send these values back to the xml, saving it.
I already call back the xml file, so that I can load the list of letters I need.
anyway, first things first, I'd need to retrieve the data from the usercontrols.
Here's the code in the form that contains quite everything:
public partial class SettingLetterInput : UserControl {
Dictionary<char, Actions> ListaLettere;
public SettingLetterInput() {
InitializeComponent();
}
private void SettingLetterInput_Load(object sender, EventArgs e) {
string path = Path.GetFullPath("Config.xml");
ListaLettere = Actions.GetFromXML(path);
listLetterBox1.Items.AddRange(
ListaLettere.Select(l => (object)l.Key).ToArray());
foreach (var a in Enum.GetValues(typeof(Actions.acts))) {
actionsBox.Items.Add(a);
}
}
private void AddActionBtn_Click(object sender, EventArgs e) {
if (actionsBox.Text != "") {
Actions.acts act = (Actions.acts)Enum.Parse(typeof(Actions.acts), actionsBox.Text);
AddRow(act, null);
} else {
MessageBox.Show("no action selected");
}
}
public void AddRow(Actions.acts act, object values) {
ActionRowCtrl arc;
#region switch per controls
switch (act) {
case Actions.acts.addPosition:
arc = new ActionRow_SizeCtrl(values);
arc.actNameLbl.Text = this.actionsBox.Text;
break;
case Actions.acts.changeColor:
arc = new ActionRow_ColorCtrl(values);
arc.actNameLbl.Text = this.actionsBox.Text;
break;
case Actions.acts.addCircle:
arc = new ActionRow_FormCtrl();
arc.actNameLbl.Text = this.actionsBox.Text;
break;
default:
arc = new ActionRowCtrl();
break;
}
#endregion
this.panel1.Controls.Add(arc);
positionRow();
}
public void positionRow() {
int lastTop = -1;
int lastHeight=0;
int rowN = 0;
foreach (ActionRowCtrl c in panel1.Controls) {
rowN++;
c.rowLbl.Text = rowN.ToString();
if (( rowN % 2 ) == 0)
c.BackColor = Color.White;
else
c.BackColor = Color.Bisque;
c.Top = 0;
if (lastTop > -1) {
c.Top = lastTop + lastHeight;
}
lastTop = c.Top;
lastHeight = c.Height;
}
}
public void deleteRow(ActionRowCtrl arc) {
this.panel1.Controls.Remove(arc);
arc.Dispose();
positionRow();
}
I do have a problem with a multithreaded TCPClient application, every Client object has a Thread that recievies and sends messages and a thread that handle the Tasks that should be handled (depending on the messages)... (for example creates and answer that the msg threads sends). But something is going wrong... the application almost allways uses 100% cpu (if any thread have a task, and thats most of the time). I also have a feeling that some threads get prioritised less then others (can see in some loggs that an operation takes longer in thread 1 then in thread 2 for exampel... Is there any nice way to handel this problem?
I would love some help or some hints!
Anything unclear just ask :)
Thanks! /Nick
//Waiting for TCP-connections and creating them as they arrive. Starts a Thread that handles the messages recieved and sent with this thread.
private void ListenForClients()
{
try
{
this.tcpListener.Start();
while (true)
{
TcpClient client = this.tcpListener.AcceptTcpClient();
Connection c = new Connection(this.parent);
connectionCollection.Add(c);
Thread clientThread = new Thread(new ParameterizedThreadStart(c.HandleClientComm));
threadCollection.Add(clientThread);
clientThread.Start(client);
}
}
catch (Exception e)
{
}
}
//Connection constructor, creates a ToDo-thread, this handles the messages (DB, Filewriting etc.) recieived and creats new ones to be sent.
public Connection()
{
this.todo = new ArrayList();
todoT = new Thread(handleToDo);
todoT.Start();
}
//Messagehandeling-thread
public void HandleClientComm(object client)
{
try
{
TcpClient server = (TcpClient)client;
NetworkStream ns = server.GetStream();
byte[] data = new byte[1024];
string input, stringData;
online = true;
DateTime lastTime = DateTime.Now;
while (true && this.online)
{
try
{
if (lastTime.AddMinutes(2) < DateTime.Now)
break;
data = new byte[1024];
if (ns.DataAvailable && ns.CanRead)
{
int recv = ns.Read(data, 0, data.Length);
if (recv > 0)
{
lastTime = DateTime.Now;
if ((byte)data[recv - 1] == (byte)255)
{
int cnt = -1;
for (int i = 0; i < recv; i++)
{
if (data[i] == (byte)254)
{
cnt = i;
break;
}
}
int nr = recv - cnt - 2;
byte[] tmp = new byte[nr];
for (int i = 0; i < nr; i++)
{
tmp[i] = data[cnt + i + 1];
}
string crc = Encoding.UTF8.GetString(tmp);
stringData = Encoding.UTF8.GetString(data, 0, cnt);
MsgStruct msgs = new MsgStruct(stringData);
msgs.setCrc(crc);
addTodo(msgs);
if (msgs.getMsg()[0] == 'T' && this.type == 1)
this.parent.cStructHandler.sendAck(msgs, this.ID);
Console.WriteLine(todo.Count);
}
}
}
if (parent.cStructHandler.gotMsg(this.ID))
{
MsgStruct tmpCs = parent.cStructHandler.getNextMsg(this.ID);
if (tmpCs.getMsg().Length != 0 && ns.CanWrite)
{
byte[] ba = Encoding.UTF8.GetBytes(tmpCs.getMsg());
if (tmpCs.getCrc() == "")
{
ulong tmp = CRC.calc_crc(ba, ba.Length);
tmpCs.setCrc(tmp.ToString("X"));
}
if (tmpCs.canSendByTimeout())
{
string crcStr = "?" + tmpCs.getCrc() + "?";
byte[] bb = Encoding.UTF8.GetBytes(crcStr);
crcStr = Encoding.UTF8.GetString(bb);
byte[] fullMsg = new byte[ba.Length + bb.Length];
bb[0] = 254;
bb[bb.Length - 1] = 255;
ba.CopyTo(fullMsg, 0);
bb.CopyTo(fullMsg, ba.Length);
string s = System.Text.UTF8Encoding.ASCII.GetString(fullMsg);
ns.Write(fullMsg, 0, fullMsg.Length);
if (!tmpCs.isAckNeeded())
parent.cStructHandler.removeNextMsg(this.ID);
}
}
}
}
catch (Exception e)
{
break;
}
}
ns.Close();
server.Close();
dead = true;
}
catch (Exception e)
{
dead = true;
}
}
//Todo-thread
public void handleToDo()
{
try
{
int cnt = 0;
while (true)
{
if (todo.Count > 0)
{
//SWITCH CASE FOR DIFFERENT MESSAGE TYPES, DOING TASKS DEPENDING ON WHAT ONES...
}
else
{
if (dead)
{
todoT.Abort();
todoT = null;
break;
}
}
}
}
}
Stop checking if data is available etc. and just let the read() block. That's how it's supposed to work!
If you want to write stuff to the socket, do it from another thread, (direct from parent thingy?), or change your design to use async reads/writes.
Looping around, polling stuff, sleep() etc. is just a waste of CPU and/or adding avoidable latency to your app.
I'm making a Windows Form Application with VS 2010. I've added a ProgressBar to my form, and I change its value. However, the ProgressBar does not advance or change. I think one of the reasons is because the process is too fast, but I made it slow and it didn't work either.
Here's the code:
void pn_TenPercentProgressEvent(object sender, PrimeNumberEventArgs e)
{
probarPrimeNumber.Visible = true;
probarPrimeNumber.Value = (int)e.Percent * 100;
this.Refresh();
}
this is the class that event occurs:
public ulong[] Generate(int count)
{
ulong[] ulngaryResult = new ulong[count];
switch (count)
{
case 0:
{
throw new Exception("The Zero is NOT Permitted.");
}
case 1:
{
ulngaryResult[0] = 2;
break;
}
case 2:
{
ulngaryResult[1] = 3;
goto case 1;
}
default:
{
int intIndex = 0;
double dblPercent = 0.1;
for (ulong i = 2; i < ulong.MaxValue; i++)
{
if (this.IsPrime(i))
{
ulngaryResult[intIndex] = i;
intIndex++;
}
if (intIndex == (int)(dblPercent * count))
{
//Raise TenPercentProgressEvent
if (TenPercentProgressEvent != null) //Optional Event
{
TenPercentProgressEvent((object)this, new PrimeNumberEventArgs(intIndex, count, dblPercent));
}
dblPercent += 0.1;
}
if (intIndex == count)
{
//Raise FinishedProgressEvent
if (FinishedProgressEvent != null) //Optional Event
{
FinishedProgressEvent((object)this, new PrimeNumberEventArgs(intIndex, count, dblPercent));
}
break;
}
}
break;
}
}
return ulngaryResult;
}
Try (int)(e.Percent * 100). As it is, casting to int before multiplying by 100 rounds to either 0 or 1 - which then translates into either 0% or 100%, all the time, but never in between.