Can't output to textblock, but messagebox works - c#

I'm having a problem with outputting to textblock. Basicly what I do is this:
private void ReadData()
{
double dHeading = 0;
int iHeading = 0;
String sString = "";
while (!stop)
{
//Get Heading
result = fsuipc.FSUIPC_Read(0x0580, 4, ref token, ref dwResult);
result = fsuipc.FSUIPC_Process(ref dwResult);
result = fsuipc.FSUIPC_Get(ref token, ref dwResult);
dHeading = dwResult;
if (dHeading != 0)
{
dHeading = dHeading * 360 / (65536.0 * 65536.0);
iHeading = Convert.ToInt32(dHeading);
}
if (iHeading < 0)
{
iHeading = 360 + Convert.ToInt32(dHeading);
}
if (iHeading == 0)
{
iHeading = 360;
}
if (result == true && iHeading < 10)
{
sString = "00" + Convert.ToString(iHeading);
}
if (result == true && iHeading >= 10 && iHeading < 100)
{
sString = "0" + Convert.ToString(iHeading);
}
if (result == true && iHeading >= 100)
{
sString = Convert.ToString(iHeading);
}
txbHeading.Text = sString;
// But if I change this line to MessageBox.Show(sString);
// it works fine.
}
}
The program freezes and I can't do anything with it. I have to stop it in VS .
If I change the txbHeading.Text = sString to MessageBox.Show(sString), it works fine.
Please note that I just started with C#.
Thanks in advance!

The while loop in your code causes the UI thread to block, so the program should stop responding when the method is called. A background worker allows your code to be executed in a seperate thread without blocking the GUI.

try
this.Invoke(new Action(() => txbHeading.Text = sString))
instead. i assume you running outside the UI thread.
More on this: The Practical Guide to Multithreading - Part 1

Related

want to press a key to stop my loop while the program is not selected c#

I'm using a Windows Form Application, and I have a loop that counts to a specific iteration, via async for loop. I have a button to stop said loop, AND a keypress that can also stop the loop. The problem with the second one however, is that when the program is NOT the active window, it completely ignores any keystroke and keeps going.
I do not know how much of my code you would need, but heres the async part of it
private async void button1_Click(object sender, EventArgs e)//Start Button
{
stopLoop = false;
cpsLabel.Text = 0.ToString();
await Task.Delay(5000);//wait 5 seconds before clicking
int speedSec = int.Parse(secondsBox.Text);
int speedMil = int.Parse(millisecondsBox.Text);
if (speedSec == 0 && speedMil == 0)
{ }
else
{
if (rightCheck.Checked == true)
{
for (int i = 0; i != int.Parse(iterations.Text) && !stopLoop; i++)
{
Application.DoEvents();
if (Control.ModifierKeys == Keys.Alt)//it should stop now
break;
DoRightMouseClick();
await Task.Delay((speedSec * 1000) + speedMil);
}
}
if (leftCheck.Checked == true)
{
for (int i = 0; i != int.Parse(iterations.Text) && !stopLoop; i++)
{
Application.DoEvents();
if (Control.ModifierKeys == Keys.Alt)//it should stop now
break;
DoLeftMouseClick();
await Task.Delay((speedSec * 1000) + speedMil);
}
}
}
cpsLabel.Text = 0.ToString();
}

C# - Peek Queue over time Without timer. Is it possible?

My current code is inside a timer to keep comparing if all drones actual position is near desired position but I dont think this is the best approach because I think this leads to slow processing.
Is there a way to check if the actual position is near desired position without using peek inside a timer?
private void timer_missao_Tick(object sender, EventArgs e)
{
string[] pontos_separados = null;
for (int k = 0; k < drone.Length; k++)
{
if (queue[k].Count > 0)
{
if (queue[k].Peek() == "levantar")
{
drone[k]._droneClient.FlatTrim();
drone[k]._droneClient.Takeoff();
drone[k].subir_ate_altura = true;
queue[k].Dequeue();
}
else if (queue[k].Peek().Split(null)[0] == "goto")
{
pontos_separados = queue[k].Peek().Split(null)[1].Split(',');
drone[k].posicao_desejada = new PointF(Convert.ToSingle(pontos_separados[0]), Convert.ToSingle(pontos_separados[1]));
int precisao = 5;
if (drone.All(d=> d.pos_atual().X > d.pos_desej().X - precisao && d.pos_atual().X <d.pos_desej().X + precisao &&
d.pos_atual().Y > d.pos_desej().Y - precisao && d.pos_atual().Y < d.pos_desej().Y + precisao))
{
for (int i = 0; i < drone.Length; i++)
{
queue[i].Dequeue();
}
}
}
else if (queue[k].Peek() == "aterrar")
{
drone[k]._droneClient.Land();
if (drone[k]._droneClient.NavigationData.State == NavigationState.Landed)
{
queue[k].Dequeue();
}
}
You could do the check only when the drone positions are updated, and not on every tick. That way you can also skip the Peek, by having the code that updates the drone position pass the updated Drone object to your check function.

C# TcpClient streamreader with eventhandler not all messages are processed

I'm reading continuously from a TcpClient streamreader.
The data coming from the stream is raw XML. There is no message framing. So there is now reliable method to know when the message is finished. Though I only have 3 XML messages coming from the server. But when they are coming is unknown. And I can't configure/program the server.
This is my code so far.
public void Start()
{
StreamReader reader = new StreamReader(_tcpClient.GetStream());
char[] chars = new char[Int16.MaxValue];
while (!_requestStop)
{
try
{
while ((reader.Read(chars, 0, chars.Length)) != 0)
{
string s = new string(chars);
s = removeEmptyChars(s);
if (s.IndexOf("<foo", StringComparison.OrdinalIgnoreCase) > 0 &&
s.IndexOf("</foo>", StringComparison.OrdinalIgnoreCase) > 0)
{
Console.WriteLine(s);
OnAlarmResponseComplete(new CustomEventArgs(s));
}
if (s.IndexOf("<bar", StringComparison.OrdinalIgnoreCase) > 0 &&
s.IndexOf("</bar>", StringComparison.OrdinalIgnoreCase) > 0)
{
Console.WriteLine(s);
OnAckComplete(new CustomEventArgs(s));
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
//break;
}
}
reader.Close();
Console.WriteLine("Stopping TcpReader thread!");
}
Then in my main thread I'm processing the events. I'm adding them to a list.
Where I process the list.
When I'm debugging my application, I will be receiving 10 foo and 10 bar messages. And in my lists I have only 1 foo and 1 bar message stored.
Are the eventhandlers to slow to process this? Or am I missing something?
Here is the code you should use to cover all kinds of input issues (foo or bar received partially, foo and bar received together, etc..)
I can't say I approve using string parsing to handle XML content, but anyways.
private static string ProcessAndTrimFooBar(string s, out bool foundAny)
{
foundAny = false;
int fooStart = s.IndexOf("<foo", StringComparison.OrdinalIgnoreCase);
int fooEnd = s.IndexOf("</foo>", StringComparison.OrdinalIgnoreCase);
int barStart = s.IndexOf("<bar", StringComparison.OrdinalIgnoreCase);
int barEnd = s.IndexOf("</bar>", StringComparison.OrdinalIgnoreCase);
bool fooExists = fooStart >= 0 && fooEnd >= 0;
bool barExists = barStart >= 0 && barEnd >= 0;
if ((fooExists && !barExists) || (fooExists && barExists && fooStart < barStart))
{
string fooNodeContent = s.Substring(fooStart, fooEnd - fooStart + 6);
s = s.Substring(fooEnd + 6);
Console.WriteLine("Received <foo>: {0}", fooNodeContent);
OnAlarmResponseComplete(new CustomEventArgs(fooNodeContent));
foundAny = true;
}
if ((barExists && !fooExists) || (barExists && fooExists && barStart < fooStart))
{
string barNodeContent = s.Substring(barStart, barEnd - barStart + 6);
s = s.Substring(barEnd + 6);
Console.WriteLine("Received <bar>: {0}", barNodeContent);
OnAckComplete(new CustomEventArgs(barNodeContent));
foundAny = true;
}
return s;
}
public static void Start()
{
StreamReader reader = new StreamReader(_tcpClient.GetStream());
char[] chars = new char[Int16.MaxValue];
while (!_requestStop)
{
try
{
int currentOffset = 0;
while ((reader.Read(chars, currentOffset, chars.Length - currentOffset)) != 0)
{
string s = new string(chars).TrimEnd('\0');
bool foundAny;
do
{
s = ProcessAndTrimFooBar(s, out foundAny);
} while (foundAny);
chars = s.PadRight(Int16.MaxValue, '\0').ToCharArray();
currentOffset = s.Length;
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
//break;
}
}
reader.Close();
Console.WriteLine("Stopping TcpReader thread!");
}

Mixed managed C++ method does not always return the same result to the calling C# code

A C++ method returns the correct value when I use a conditional breakpoint, but an incorrect value without a breakpoint.
C# method which calls C++:
bool SetProperty(Element element, Node referencePoint, List<Materializer> materializers, List<ulong> properties)
{
// Loop over STLs
for (int i = 0; i < materializers.Count; i++)
{
Materializer materializer = materializers[i];
if (materializer.IsPointInside(referencePoint.X, referencePoint.Y, referencePoint.Z, pentalTreeDatasets[i].top))
{
element.PropertyId = properties[i];
return true;
};
}
return false;
}
C++ methods in the header file:
int CountIntersects(double x, double y, double z, PentalTreeNode ^root)
{
Math3d::M3d rayPoints[2], intersectionPoint;
rayPoints[0].set(x,y,z);
rayPoints[1].set(x,y,1.0e6);
if(!root)
return 0;
else
{
int special = CountIntersects(x,y,z,root->special);
if (x <= root->xMax && x >= root->xMin && y <= root->yMax && y >= root->yMin)
{
if( _stlMesh->IsRayIntersectsPoly(root->index, rayPoints, intersectionPoint))
{
return (1 + special);
}
else
return special;
}
else
{
if (y>root->yMax)
{
return (CountIntersects(x,y,z,root->top)+special);
}
else if(y<root->yMin)
{
return (CountIntersects(x,y,z,root->bottom)+special);
}
else if(x<root->xMin)
{
return (CountIntersects(x,y,z,root->left)+special);
}
else if(x>root->xMax)
{
return (CountIntersects(x,y,z,root->right)+special);
}
else
return special;
}
}
}
bool IsPointInside(double x, double y, double z, PentalTreeNode ^root)
{
int intersectionCount = 0;
Math3d::M3d rayPoints[2], intersectionPoint;
rayPoints[0].set(x,y,z);
rayPoints[1].set(x,y,1.0e6);
if(_box->IsContainingPoint(x,y,z))
{
intersectionCount=CountIntersects(x,y,z,root);
return (intersectionCount%2!=0);
}
}
C++ methods in other header files:
bool IsRayIntersectsPoly(int nPolygonIndex, Math3d::M3d RayPoints[2], CVector3D& IntersectionPoint)
{
CMeshPolygonBase& Poly = m_PolygonArray[nPolygonIndex];
CArrayResultI Result;
int* pPolygonPoints = GetPolygonPoints(Poly, Result);
Math3d::MPlane TrianglePlane;
double Atmp[3], A;
CVector3D* pPoints[3];
pPoints[0] = &m_PointArray[*pPolygonPoints].m_Position;
for(int i = 1; i < Result.GetSize() - 1; i++)
{
pPoints[1] = &m_PointArray[*(pPolygonPoints+i)].m_Position;
pPoints[2] = &m_PointArray[*(pPolygonPoints+i+1)].m_Position;
TrianglePlane.Init(*pPoints[0], *pPoints[1], *pPoints[2]);
TrianglePlane.IntersectLine(RayPoints[0], RayPoints[1], IntersectionPoint);
A = GetTriangleArea(*pPoints[0], *pPoints[1], *pPoints[2]);
for(int j = 0; j < 3; j++)
{
Atmp[j] = GetTriangleArea(*pPoints[j], *pPoints[(j+1)%3], IntersectionPoint);
}
if( fabs(A - Atmp[0] - Atmp[1] - Atmp[2]) < 1.0e-5 ) return true;
}
return false;
};
double GetTriangleArea(CVector3D& T1, CVector3D& T2, CVector3D& T3)
{
double a, b, c, s;
a = (T1 - T2).length();
b = (T2 - T3).length();
c = (T3 - T1).length();
s = 0.5 * (a + b + c);
return( sqrt(s * (s - a)* (s - b)* (s - c)) );
}
When I start the program which calls SetProperty() within the for-loop, the results for some iterator values are wrong. When I set conditional breakpoints for critical iterator values in the for-loop and step over it, then the result is OK for that item. What may be the problem?
This is method in which I post breakpoint. For example, for critical element.Id==2393.
private void StartButton_Click(object sender, EventArgs e)
{
DateTime startTime = DateTime.Now;
List<Materializer> materializers = new List<Materializer>();
List<ulong> properties = new List<ulong>();
// Load STLs
for (int i = 0; (int)i < (this.dataGridView.RowCount - 1); i++)
{
if (dataGridView.Rows[i].Cells[1].Value != null && (string)dataGridView.Rows[i].Cells[1].Value != "")
{
Materializer materializer = new Materializer();
materializer.LoadSTLMesh(dataGridView.Rows[i].Cells[0].Value.ToString());
materializers.Add(materializer);
properties.Add((ulong)dataGridView.Rows[i].Cells[1].Tag);
}
}
CreatePentalTrees(materializers);
int processedElementCount = 0;
int changedElementCount = 0;
// Loop over elements
foreach (Element element in model.ElementsList.Values)
if ((element.Topology == 7 || element.Topology == 8) && !lockedProperties.ContainsKey(element.PropertyId)) // 3D elements only
{
Node center = this.CenterPoint(element, model.NodesList);
if (element.Id == 2393)
{
//if breakpoints thats ok, else not ok
Console.WriteLine(element.Id);
Console.WriteLine(element.PropertyId);
}
if (SetProperty(element, center, materializers, properties)) // Check for center point
{
//changedElements.Add(element.Id, true);
changedElementCount++;
}
else
{
// Check for all nodes if center point does not belong to any STL
int[] nodeOrder;
switch (element.Topology)
{
case 7:
nodeOrder = wedgeNodeOrder;
break;
case 8:
nodeOrder = brickNodeOrder;
break;
default:
throw new Exception("Unknown topology " + element.Topology.ToString());
}
for (int i = 0; i < nodeOrder.Length; i++)
{
Node node = model.NodesList[element.NodeIds[nodeOrder[i]]];
if (SetProperty(element, node, materializers, properties))
{
//changedElements.Add(element.Id, true);
changedElementCount++;
break;
}
}
}
if (++processedElementCount % 100 == 0)
{
labelTime.Text = "Changed/processed elements: " + changedElementCount.ToString() + "/" + processedElementCount.ToString();
labelTime.Refresh();
Application.DoEvents();
}
}
DateTime endTime = DateTime.Now;
labelTime.Text = "Total time: " + (endTime - startTime).TotalSeconds.ToString() + " s";
MessageBox.Show("Completed.");
SaveFileDialog saveFileDlg = new SaveFileDialog();
saveFileDlg.Title = "Save FEMAP neutral file";
saveFileDlg.Filter = "(*.neu)|*.neu";
if (saveFileDlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
FemapNeutral.ExportNeu(saveFileDlg.FileName, model);
}
}
You seem to be calling a lot of methods you haven't listed, and/or the wall of code made me get lost. Adding that code won't help: reducing your problem to a simpler one that demonstrates the problem might.
However, the most likely cause of your problem, if you have unmanaged code reading managed data, is that you failed to marshal or pin the data prior to using the managed code.
Unpinned data can be moved around by the garbage collector in unexpected ways.

Exce­pti­on with th­re­ads in ­wp­f a­pp

Hi guys I receive an exception if (checkBox1.IsChecked == true || checkBox2.IsChecked == true):
The calling thread cannot access this object because a different
thread owns it.
in my wpf app:
private void button1_Click(object sender, RoutedEventArgs e)
{
int i = 0;
int j = Int32.Parse(textBox1.Text);
thr = new Thread[j];
for (; i < j; i++)
{
thr[i] = new Thread(new ThreadStart(go));
thr[i].IsBackground = true;
thr[i].Start();
}
}
public void go()
{
while (true)
{
string acc = "";
string proxy = "";
if (checkBox1.IsChecked == true || checkBox2.IsChecked == true)
{
if (checkBox1.IsChecked == true)
Proxy.type = "http";
else if (checkBox2.IsChecked == true)
Proxy.type = "socks5";
else
Proxy.type = "none";
proxy = rand_proxy();
}
}
}
Why?
You cannot access UI elements from a thread other than one which was those created. Your check boxes are created on UI thread and you can access these only on UI thread.
try this.
public void go()
{
Dispatcher.BeginInvoke(new Action(()=>{
while (true)
{
string acc = "";
string proxy = "";
if (checkBox1.IsChecked == true || checkBox2.IsChecked == true)
{
if (checkBox1.IsChecked == true)
Proxy.type = "http";
else if (checkBox2.IsChecked == true)
Proxy.type = "socks5";
else
Proxy.type = "none";
proxy = rand_proxy();
}
}), null);
}
You cannot access UI elements on a different thread than the UI. To work around this, you can check
checkBox1.Dispatcher.CheckAccess()
and if true, use
checkBox1.Dispatcher.Invoke
or
checkBox1.Dispatcher.BeginInvoke
Use CheckAccess to see if you need call Dispatcher.BeginInvoke or Invoke
See also this post
Basically you're not allowed to access controls from threads other than the thread they were created on. There's a good explanation of the WPF threading model here, and this walks through the issue you are describing.
Good luck.

Categories

Resources