I am writing a simple tcp communication program in c#. What i want is to start the timer by enabling it when client receieves a certain message. Problem is, timer does not tick when its enabled. I am using System.Windows.Forms.Timer.
void ReceiveData()
{
int recv;
string stringData;
while (true)
{
recv = client.Receive(data);
stringData = Encoding.ASCII.GetString(data, 0, recv);
if (stringData == "/starttimer" & !timer1.Enabled)
{
timer1.Enabled = true;
break;
}
}
}
Stopwatch player1timer = new Stopwatch();
void timer1_Tick(object sender, EventArgs e)
{
if (player1timer.IsRunning)
{
pl1label.Text = Convert.ToDouble(2) - Convert.ToDouble(player1timer.Elapsed.Minutes.ToString("00")) ":"
Convert.ToString(Convert.ToDouble(59) - Convert.ToDouble(player1timer.Elapsed.Seconds.ToString("00"))) "."
Convert.ToString(Convert.ToDouble(999) - Convert.ToDouble(player1timer.Elapsed.Milliseconds.ToString("00")));
}
}
CodePudding user response:
Since this is a UI program you need to be careful to avoid blocking the UI thread.
In your example the Receive
will probably block the UI thread until there is some data. And it will continue to do so if the timer is already enabled, or if it does not receive the required message. This will prevent the UI from doing other things, like updating the graphics, or to handle mouse and keyboard events. Never block the UI thread
To avoid this you need to either use asynchronous programming or background threads. Since background threads require a fairly good understanding of thread safety I would recommend the async approach.
I do not have any complete example, and such an example might be counter productive if this is homework, but the overall approach should be:
- Create a TcpClient from a TcpListner
- Get a NetworkStream from the
TcpClient.GetStream()
- Wrap this stream inside a streamReader, and use
ReadLineAsync()
to read lines. Use whatever text-encoding you want when creating your reader. - await the returned task to get the actual string.
You can do this inside an infinite loop inside an async method. This should not block, since the await
will let the UI thread do other things while it waits for data. Keep in mind to wrap the contents of the method in a try/catch, since it is otherwise possible for exceptions to get lost.
This should be appropriate for a simple application demonstrating the concepts, but for real world usage I would highly recommend using a library to handle communication. That will most likely be much easier to use.
Note that some methods returning tasks lie, and are really synchronous methods pretending to be async. This will obviously not work, but it can be difficult to tell from the documentation, so it is often easiest to just try.