Why doesn't this thread ever end? - c#

I'm trying to control a piece of test equipment and I need to get the sequencing correct of how I communicate with it.
First I call StartGettingTraceData(). Then some time in the future I call StopGettingTraceData() to attempt to end the GetTraceData() function instead of it re-launching itself. But that NEVER happens. In fact, I never get to the line DoneTraces.Set() so on the line bool timedOut = !DoneTraces.WaitOne(10000), timedOut always is true;
private static AutoResetEvent DoneTraces = new AutoResetEvent(false);
private void GetTraceData()
{
byte[] receivedbytes = new byte[1];
if (Connection.ReadData(receivedbytes) && receivedbytes[0] == 192)
ProcessIncomingTrace();
Thread.Sleep(100);
if (RunTraceQueryWorker)
new Thread(GetTraceData).Start();
else
{
Thread.Sleep(200);
DoneTraces.Set();
}
}
private void StartGettingTraceData()
{
RunTraceQueryWorker = true;
new Thread(GetTraceData).Start();
}
private bool StopGettingTraceData()
{
RunTraceQueryWorker = false;
bool timedOut = !DoneTraces.WaitOne(10000);
return timedOut;
}
Any thoughts on what is going on?
EDIT:
Here is my Connection.ReadData(...) function. It's a serial connection by the way.
public bool ReadData(byte[] responseBytes)
{
int bytesExpected = responseBytes.Length, offset = 0, bytesRead;
while (bytesExpected > 0 && (bytesRead = MySerialPort.Read(responseBytes, offset, bytesExpected)) > 0)
{
offset += bytesRead;
bytesExpected -= bytesRead;
}
return bytesExpected == 0;
}

Rather than recusively calling GetTraceData again, you should use a while loop looking at your condition like this:
private static AutoResetEvent DoneTraces = new AutoResetEvent(false);
private void GetTraceData()
{
do
{
byte[] receivedbytes = new byte[1];
if (Connection.ReadData(receivedbytes) && receivedbytes[0] == 192)
ProcessIncomingTrace();
Thread.Sleep(100);
}
while (RunTraceQueryWorker)
Thread.Sleep(200);
DoneTraces.Set();
}
private void StartGettingTraceData()
{
RunTraceQueryWorker = true;
new Thread(GetTraceData).Start();
}
private bool StopGettingTraceData()
{
RunTraceQueryWorker = false;
bool timedOut = !DoneTraces.WaitOne(10000);
return timedOut;
}
It's impossible to know specifically why your code is freezing without understanding what ReadData & ProcessIncomingTrace() do.

Well, chances are that the ReadData call is blocking. As an aside, you're making it hard on yourself with all this recursive threading... Can't you just use a loop?
private void GetTraceData()
{
byte[] receivedbytes = new byte[1];
while( RunTraceQueryWorker )
{
if( Connection.ReadData(receivedbytes) && receivedbytes[0] == 192 )
{
ProcessIncomingTrace();
}
Sleep(100);
}
Thread.Sleep(200);
DoneTraces.Set();
}

Related

c# How can I call a void after another void?

I have two voids that have to be called after one another every 5 seconds.I mean first the first void has to be called and after that the second void has to be called and the we have 5 seconds break...but my program only calls the first void(get pressure) and ignores the second one....could anyone show me the code?
private void getPressure()
{
if (serialPort1.IsOpen)
{
string PCR = "";
byte[] readCommand = { 0x50, 0x0D };
serialPort1.Write(readCommand, 0, 2);
int bytestoread = serialPort1.BytesToRead;
if (bytestoread > 0)
{
byte[] input = new byte[bytestoread];
serialPort1.Read(input, 0, bytestoread);
PCR = System.Text.Encoding.UTF8.GetString(input);
}
if (PCR.StartsWith("P"))
{
if (PCR.Length > 15)
{
PCR = PCR.Substring(3, PCR.IndexOf("T") - 3).Trim();
var decPCR = Decimal.Parse(PCR, NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint);
rTxtBoxPressure.Text = decPCR + " Torr";
double data;
bool result = Double.TryParse(decPCR.ToString(), out data);
if (result)
{
serialDataChart.TriggeredUpdate(data);
}
}
}
}
}
private void getVoltage()
{
if (serialPort1.IsOpen)
{
string UCR = "";
byte[] readCommand2 = { 0x55, 0x0D };
serialPort1.Write(readCommand2, 0, 2);
int bytestoread2 = serialPort1.BytesToRead;
if (bytestoread2 > 0)
{
byte[] input2 = new byte[bytestoread2];
serialPort1.Read(input2, 0, bytestoread2);
UCR = System.Text.Encoding.UTF8.GetString(input2);
}
if (UCR.StartsWith("V"))
{
if (UCR.Length > 15)
{
UCR = UCR.Substring(5, UCR.IndexOf("Volts") - 5).Trim();
var decUCR = Decimal.Parse(UCR, NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint);
rtxtBoxVoltage.Text = decUCR + " Volts";
double data;
bool result = Double.TryParse(decUCR.ToString(), out data);
if (result)
{
serialDataChart2.TriggeredUpdate(data);
}
}
}
}
}
private void InitTimer()
{
timer1 = new Timer();
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Interval =5000;
timer1.Start();
}
private void timer1_Tick(object sender , EventArgs e)
{
getPressure();
getVoltage();
}
First of all, you define your time with Interval = 5000, which will trigger timer event every 5 seconds.
Secondly, in timer event handler you call desired methods one after another, without any interval, so once getPressure finishes, getVoltage starts immediately.
So, to sum it up - you don't need timer, as in your requirements I don't see that both functions should be called periodically. The only thing we need to call one, and then after 2 seconds call another, so I'd suggest something among the lines
getPressure();
// wait two seconds between calls, you could also use Thread.Sleep(2 * 1000)
await Task.Delay(2 * 1000);
getVoltage();
IF you want to wait 2 seconds before calling getVoltage, but it should be 2 seconds from starting getPressure, then the code should look like:
var pressureTask = Task.Run(() => getPressure());
await Task.Delay(2 * 1000);
getVoltage();
await pressureTask;

Sending Pictures over Network with Unity C#

I am currently working with the HoloLens and thus Unity. The idea is to make a webcam Livestream with as little delay as possible to an instance of FFmpeg on a different device for encoding. However, I run into some issues.
My first problem is the Conversion from a Color32 Array to a Byte Array. It creates a huge amount of bandwidth, especially when I am trying to record and stream with 30fps and a 1280x720 resolution.
Here is some code:
IEnumerator Init()
{
webCam = new WebCamTexture(1280, 720, 30);
webCam.Play();
image.texture = webCam;
Debug.Log("WebCam Width: " + webCam.width);
Debug.Log("WebCam Height: " + webCam.height);
currentTexture = new Texture2D(webCam.width, webCam.height);
data = new Color32[webCam.width * webCam.height];
listener = new TcpListener(IPAddress.Any, 10305);
listener.Start();
while (webCam.width < 100)
{
yield return null;
}
StartCoroutine("Recording");
}
WaitForEndOfFrame endOfFrame = new WaitForEndOfFrame();
IEnumerator Recording()
{
TcpClient tcpClient = null;
NetworkStream tcpStream = null;
bool isConnected = false;
Loom.RunAsync(() =>
{
while(!stopCapture)
{
tcpClient = listener.AcceptTcpClient();
Debug.Log("Client Connected!");
isConnected = true;
tcpStream = tcpClient.GetStream();
}
});
while(!isConnected)
{
yield return endOfFrame;
}
readyToGetFrame = true;
byte[] messageLength = new byte[SEND_RECEIVE_COUNT];
while(!stopCapture)
{
yield return endOfFrame;
webCam.GetPixels32(data);
byte[] webCamBytes = Utilities.Color32ArrayToByteArray(data);
readyToGetFrame = false;
Loom.RunAsync(() => {
tcpStream.Write(webCamBytes, 0, webCamBytes.Length);
readyToGetFrame = true;
});
while (!readyToGetFrame)
{
yield return endOfFrame;
}
}
}
public static class Utilities
{
public static byte[] Color32ArrayToByteArray(Color32[] colors)
{
if (colors == null || colors.Length == 0)
{
return null;
}
int lengthOfColor32 = Marshal.SizeOf(typeof(Color32));
int byteArrayLength = lengthOfColor32 * colors.Length;
byte[] bytes = new byte[byteArrayLength];
GCHandle handle = default(GCHandle);
try
{
handle = GCHandle.Alloc(colors, GCHandleType.Pinned);
IntPtr ptr = handle.AddrOfPinnedObject();
Marshal.Copy(ptr, bytes, 0, byteArrayLength);
}
finally
{
if(handle != default(GCHandle))
{
handle.Free();
}
}
return bytes;
}
}
To fix this problem, I tried to use EncodePNG and EncodeJPG instead. But there is my second problem. If I use these methods, I got a big loss of performance.
So instead of this
webCam.GetPixels32(data);
byte[] webCamBytes = Utilities.Color32ArrayToByteArray(data);
I use this
currentTexture.SetPixels(webCam.GetPixels());
byte[] webCamBytes = currentTexture.EncodeToJPG();
Thus my question:
Is there any way to reduce the bandwith by maybe cutting off the alpha values as they are not needed? Or is there another good way such as converting to a different color or picture format?
Because right now I ran out of usable ideas and feel kinda stuck. Might just be me though ;-)
PS: Using external libraries is a tad difficult as it needs to run on HoloLens and due to other regulations.
Thank you in advance!

C# - Application freezing suddenly

I am actually making a game, the issue is that when a card moves (I'm using Timer), it makes me freeze the entire form, sometimes it manages to load, sometimes it freezes the entire game. (+ prevents from clicking a label and clicking a MessageBox)
Issue : (.png)
Here
Code : (timers)
public void moveCardsAdv6_2_Tick(object sender, EventArgs e)
{
if (Partie)
{
Distrib = true;
int y6_2 = 48;
int x6_2 = 13;
pictureBoxd6_2.Top += y6_2;
pictureBoxd6_2.Left += x6_2;
#region Adversaire 6
if (pictureBoxd6_2.Top >= 560 && pictureBoxd6_2.Left >= 110)
{
dist6_1 = true;
SecondDistr = true;
moveCardsAdv6_2.Stop();
pictureBoxd6_2.Location = pictureBoxDeck.Location;
GenCartesAdv();
dist6_1 = false;
SecondDistr = false;
moveCardsAdv7_2.Enabled = true;
moveCardsAdv7_2.Start();
}
#endregion
}
}
Card gen code
#region Adversaire 6
int CarteAleaA6 = CarteAleatoire();
Cartes carteA6 = jeu[CarteAleaA6];
CartesUtilisees.Add(CarteAleaA6);
int CarteAleaA6_2 = CarteAleatoire();
while (CartesUtilisees.Contains(CarteAleaA6_2))
{
CarteAleaA6_2 = CarteAleatoire();
}
CarteAleaA6_2 = 1 * CarteAleaA6_2;
ListeCartes.Add(carteA6);
if (Distrib && dist6_1)
{
if (SecondDistr == false)
{
pictureBoxAdv6_1.ImageLocation = carteA6.Image;
}
else
{
Cartes carteA6_2 = jeu[CarteAleaA6_2];
CartesUtilisees.Add(CarteAleaA6_2);
ListeCartes.Add(carteA6_2);
pictureBoxAdv6_2.ImageLocation = carteA6_2.Image;
}
}
#endregion
As the others suggested, maybe try moving them into asnyc functions and await them.
public async void moveCardsAdv6_2_Tick(object sender, EventArgs e)
{
await moveCardsAdv6_2_TickAsync();
}
private async Task moveCardsAdv6_2_TickAsync()
{
if (Partie)
{
Distrib = true;
int y6_2 = 48;
int x6_2 = 13;
pictureBoxd6_2.Top += y6_2;
pictureBoxd6_2.Left += x6_2;
#region Adversaire 6
if (pictureBoxd6_2.Top >= 560 && pictureBoxd6_2.Left >= 110)
{
dist6_1 = true;
SecondDistr = true;
moveCardsAdv6_2.Stop();
pictureBoxd6_2.Location = pictureBoxDeck.Location;
GenCartesAdv();
dist6_1 = false;
SecondDistr = false;
moveCardsAdv7_2.Enabled = true;
moveCardsAdv7_2.Start();
}
#endregion
}
}

MediaFoundationResampler of audio loopback stream is alway read as 0 bytes

I can see that the system audio for WasapiLoopbackCapture is not the right rate to try and get Microsoft Windows' audio to text recognition working (only 8/16 is supported, eg AudioBitsPerSample.Sixteen ), from the output of this program. The odd thing I cannot figure out is why the resampler in this code is never called. I set a breakpoint - even wait 5s for the system audio to play and be placed in the buffer. I am trying to get system sound, to text using the audio speech recognizer. I can see that bytes are written to captureStream during debugging, so why does the resampler never output bytes? - The Console.WriteLine("Never getting here"); is never getting there.
using System;
using System.Speech.Recognition;
using NAudio.Wave;
using NAudio.CoreAudioApi.Interfaces;
using NAudio.CoreAudioApi;
using System.IO;
using System.Speech.AudioFormat;
namespace SpeechRecognitionApp
{
class FakeStreamer : Stream
{
public bool bExit = false;
Stream stream;
Stream client;
public FakeStreamer(Stream client)
{
this.client = client;
this.stream = client;
}
public override bool CanRead
{
get { return stream.CanRead; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return stream.CanWrite; }
}
public override long Length
{
get { return -1L; }
}
public override long Position
{
get { return 0L; }
set { }
}
public override long Seek(long offset, SeekOrigin origin)
{
return 0L;
}
public override void SetLength(long value)
{
stream.SetLength(value);
}
public override int Read(byte[] buffer, int offset, int count)
{
int len = 0, c = count;
while (c > 0 && !bExit)
{
try
{
len = stream.Read(buffer, offset, c);
}
catch (Exception e)
{
Console.WriteLine("ouch");
}
/*if (!client.Connected || len == 0)
{
//Exit read loop
return 0;
}*/
offset += len;
c -= len;
}
return count;
}
public override void Write(byte[] buffer, int offset, int count)
{
stream.Write(buffer, offset, count);
}
public override void Close()
{
stream.Close();
base.Close();
}
public override void Flush()
{
stream.Flush();
}
}
class Program
{
static void Main(string[] args)
{
// Create an in-process speech recognizer for the en-US locale.
using (
SpeechRecognitionEngine recognizer =
new SpeechRecognitionEngine(
new System.Globalization.CultureInfo("en-US")))
{
// Create and load a dictation grammar.
recognizer.LoadGrammar(new DictationGrammar());
// Add a handler for the speech recognized event.
recognizer.SpeechRecognized +=
new EventHandler<SpeechRecognizedEventArgs>(recognizer_SpeechRecognized);
// Configure input to the speech recognizer.
//recognizer.SetInputToDefaultAudioDevice();
WasapiLoopbackCapture capture = new WasapiLoopbackCapture();
Stream captureStream = new System.IO.MemoryStream();
//Stream buffStream = new FakeStreamer(captureStream);
capture.DataAvailable += (s, a) =>
{
//It is getting here.
captureStream.Write(a.Buffer, 0, a.BytesRecorded);
};
Console.WriteLine(capture.WaveFormat.AverageBytesPerSecond);
Console.WriteLine(capture.WaveFormat.BitsPerSample);
var newFormat = new WaveFormat(8000, 16, 1);
//using (var conversionStream = new WaveFormatConversionStream(newFormat, capture)
//capture.StartRecording();
using (var resampler = new MediaFoundationResampler(new NAudio.Wave.RawSourceWaveStream(captureStream, capture.WaveFormat), newFormat))
{
Stream captureConvertStream = new System.IO.MemoryStream();
resampler.ResamplerQuality = 60;
//WaveFileWriter.WriteWavFileToStream(captureConvertStream, resampler);
//recognizer.SetInputToDefaultAudioDevice();
Stream buffStream = new FakeStreamer(captureConvertStream);
recognizer.SetInputToAudioStream(buffStream, new SpeechAudioFormatInfo(
8000, AudioBitsPerSample.Sixteen, AudioChannel.Mono));
// Start asynchronous, continuous speech recognition.
recognizer.RecognizeAsync(RecognizeMode.Multiple);
capture.StartRecording();
//Never getting to the resampler, the read is always zero!? even if waiting 5s for the audio to buffer.
System.Threading.Thread.Sleep(5000);
var arr = new byte[128];
while (resampler.Read(arr, 0, arr.Length) > 0)
{
captureConvertStream.Write(arr, 0, arr.Length);
Console.WriteLine("Never getting here");
}
// Keep the console window open.
while (true)
{
Console.ReadLine();
}
}
}
}
// Handle the SpeechRecognized event.
static void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
Console.WriteLine("Recognized text: " + e.Result.Text);
}
}
}

Implement Dispose to my method

I have a Winform application that uses Pcapdot.Net DLLs and plays Pcap files.
When I am playing a file in a loop I can see that the application memory is raised until a crash occurs and in stack trace I can see that this happens in the method that plays the file.
So I was thinking to add dispose method and see if it can solve this crash.
So I added to my class a variable private bool _disposed;
and methods:
public void Dispose()
{
Dispose(true);
}
private virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
}
_disposed = true;
}
}
my play method:
public bool sendBuffer(PacketDevice packetDevice)
{
int count = 0;
bool bContinuePlay = true;
PacketDevice selectedOutputDevice = packetDevice;
_shouldContinue = true;
_isStop = true;
_stopButton = true;
OfflinePacketDevice selectedInputDevice = new OfflinePacketDevice(_filePath.FullName); //open the capture file
DateTime time = DateTime.Now;
double totalTime = 0;
double totalDelayTime = 0;
double deletaTime = 0;
using (inputCommunicator = selectedInputDevice.Open(65536, PacketDeviceOpenAttributes.Promiscuous, 1000))
{
using (OutputCommunicator = selectedOutputDevice.Open(100, PacketDeviceOpenAttributes.Promiscuous, 1000))
{
ThreadStart tStarter = delegate { openAdapterForStatistics(selectedOutputDevice); };
Thread thread = new Thread(tStarter);
thread.IsBackground = true;
thread.Start();
DateTime lastTime = DateTime.MinValue;
double delayTime = 0;
Packet packet;
IEnumerable<Packet> packets;
while (inputCommunicator.ReceivePacket(out packet) == PacketCommunicatorReceiveResult.Ok && _isStop) //fill the buffer with the packets from the file
{
if (count < _numberOfPacketsInfile)
{
using (PacketSendBuffer mSendBuffer = new PacketSendBuffer((uint)packet.Length * 4))
{
if (_isBurst)
{
if (lastTime != DateTime.MinValue)
{
if (packet != null)
{
delayTime = (packet.Timestamp.Subtract(lastTime).TotalMilliseconds) / _playSpeed; //delay between packets
}
if (delayTime > 1000)
{
if (_startTimer != null)
{
_startTimer(delayTime, EventArgs.Empty);
}
_delayForNextPacket = delayTime;
}
totalDelayTime += delayTime;
delayTime = delayTime - deletaTime;
if (delayTime < 0)
{
delayTime = 0;
}
if (evePacketProgress != null)
{
int packetProgressPrecentage = (int)(((double)_numberOfSendPackets / _numberOfPacketsInfile) * 100);
evePacketProgress(packetProgressPrecentage);
}
_mrEvent.WaitOne((int)delayTime);
if (_stopTimer != null)
{
_stopTimer(delayTime, EventArgs.Empty);
}
} //end if
} // end if _brust
if (_fragmentation)
{
foreach (Packet item in splitPacket(packet, 1))
{
mSendBuffer.Enqueue(item);
}
}
else if (packet != null)
{
lastTime = packet.Timestamp;
mSendBuffer.Enqueue(packet);
}
if (evePacketProgress != null)
{
int packetProgressPrecentage = (int)(((double)_numberOfSendPackets / _numberOfPacketsInfile) * 100);
evePacketProgress(packetProgressPrecentage);
}
try
{
OutputCommunicator.Transmit(mSendBuffer, _isBurst); //send the packet
_numberOfSendPackets++;
}
catch (Exception)
{
}
}///
totalTime = DateTime.Now.Subtract(time).TotalMilliseconds;
deletaTime = totalTime - totalDelayTime;
count++;
}
} //end while
}
}
return bContinuePlay;
}
the crash occur in the line DateTime lastTime = DateTime.MinValue;
I am a new developer and do not know how to proceed from here.
Any help is welcome
The Dispose method is used to free unmanaged resources, in other words, what isn't in ".NET World", like a TCP or database connection.
When CLR finds that your program is running out of memory, it automaticaly invokes Garbage Collector, that free the objects you are not using anymore.
You only need to implement IDisposable if you have to free unmanaged resources. For details implementing IDisposable, you can find a lot of articles online. For instace, you are forgeting of implement your class finalizer.
So, if the problem is in the method that play the files, you must first find what is causing the memory to increase and cannot be released by GC.
I don't know Pcapdot.Net, but try to find a method for releasing the file being played, or something like this. Maybe you don't need to implement IDisposable, just add the call for this method.

Categories