UserAppDataReigistry not persisting - c#

I have the following class to persist my camera settings.
using System;
using System.Drawing;
using System.Windows.Forms;
using DevExpress.XtraEditors.Camera;
public class CameraDeviceHelper
{
public string DeviceMoniker;
public string DeviceName;
public int DeviceResolutionWidth;
public int DeviceResolutionHeight;
const string kDeviceName = "CameraDeviceName";
const string kDeviceMoniker = "CameraDeviceMoniker";
const string kDeviceResolutionWidth = "CameraDeviceResolutionWidth";
const string kDeviceResolutionHeight = "CameraDeviceResolutionHeight";
public bool SaveCameraDevice(CameraControl cc)
{
try
{
DeviceMoniker = cc.Device.DeviceMoniker;
DeviceName = cc.Device.Name;
DeviceResolutionWidth = cc.Device.Resolution.Width;
DeviceResolutionHeight = cc.Device.Resolution.Height;
Application.UserAppDataRegistry.SetValue(kDeviceName, DeviceName);
Application.UserAppDataRegistry.SetValue(kDeviceMoniker, DeviceMoniker);
Application.UserAppDataRegistry.SetValue(kDeviceResolutionWidth, DeviceResolutionWidth);
Application.UserAppDataRegistry.SetValue(kDeviceResolutionHeight, DeviceResolutionHeight);
return true;
}
catch (Exception)
{
return false;
}
}
public bool RestoreCameraDevice(CameraControl cc)
{
try
{
DeviceName = Application.UserAppDataRegistry.GetValue(kDeviceName, DeviceName).ToString();
DeviceMoniker =Application.UserAppDataRegistry.GetValue(kDeviceMoniker, DeviceMoniker).ToString();
DeviceResolutionWidth = (int) Application.UserAppDataRegistry.GetValue(kDeviceResolutionWidth, DeviceResolutionWidth);
DeviceResolutionHeight = (int)Application.UserAppDataRegistry.GetValue(kDeviceResolutionHeight, DeviceResolutionHeight);
var moniker = new DevExpress.Data.Camera.CameraDeviceInfo(DeviceMoniker, DeviceName);
cc.Device = new CameraDevice(moniker);
var sz = new Size(DeviceResolutionWidth,DeviceResolutionHeight);
cc.Device.Resolution = sz;
if (cc.Device.Resolution.Width != sz.Width)
{ MessageBox.Show("Not set");}
cc.Start();
return true;
}
catch (Exception)
{
return false;
}
}
}
}
The persisting works while the application runs.
However when I restart the application the settings are lost.
I call the methods in my form's load and FormClosed events
private void Camera_Load(object sender, EventArgs e)
{
textEdit1.Text = PhotoCaption;
cameraDeviceHelper = new CameraDeviceHelper();
try
{
cameraDeviceHelper.RestoreCameraDevice(cameraControl1);
}
catch (Exception)
{
// probably first time... so just dont complain
throw;
}
}
private void Camera_FormClosed(object sender, FormClosedEventArgs e)
{
cameraDeviceHelper.SaveCameraDevice(cameraControl1);
}

The solution is not to have an * in the AssemblyVersion
otherwise every time the application is built the registry key will change.

Related

How to find items in a ListBox?

I am creating an application where I have a ListBox which has items that are read in from a text file using StreamReader. I have created a search form but I'm not sure what to do next. Can anyone give me some suggestions please? Here is my code:
My code for the ListBox (sorry it's so long)
public partial class frmSwitches : Form
{
public static ArrayList switches = new ArrayList();
public static frmSwitches frmkeepSwitches = null;
public static string inputDataFile = "LeckySafe.txt";
const int numSwitchItems = 6;
public frmSwitches()
{
InitializeComponent();
frmkeepSwitches = this;
}
private void btnDevices_Click(object sender, EventArgs e)
{
frmDevices tempDevices = new frmDevices();
tempDevices.Show();
frmkeepSwitches.Hide();
}
private bool fileOpenForReadOK(string readFile, ref StreamReader dataIn)
{
try
{
dataIn = new StreamReader(readFile);
return true;
}
catch (FileNotFoundException notFound)
{
MessageBox.Show("ERROR Opening file (when reading data in) - File could not be found.\n"
+ notFound.Message);
return false;
}
catch (Exception e)
{
MessageBox.Show("ERROR Opening File (when reading data in) - Operation failed.\n"
+ e.Message);
return false;
}
}
private bool getNextSwitch(StreamReader inNext, string[] nextSwitchData)
{
string nextLine;
int numDataItems = nextSwitchData.Count();
for (int i = 0; i < numDataItems; i++)
{
try
{
nextLine = inNext.ReadLine();
if (nextLine != null)
nextSwitchData[i] = nextLine;
else
{
return false;
}
}
catch (Exception e)
{
MessageBox.Show("ERROR Reading from file.\n" + e.Message);
return false;
}
}
return true;
}
private void readSwitches()
{
StreamReader inSwitches = null;
Switch tempSwitch;
bool anyMoreSwitches = false;
string[] switchData = new string[numSwitchItems];
if (fileOpenForReadOK(inputDataFile, ref inSwitches))
{
anyMoreSwitches = getNextSwitch(inSwitches, switchData);
while (anyMoreSwitches == true)
{
tempSwitch = new Switch(switchData[0], switchData[1], switchData[2], switchData[3], switchData[4], switchData[5]);
switches.Add(tempSwitch);
anyMoreSwitches = getNextSwitch(inSwitches, switchData);
}
}
if (inSwitches != null) inSwitches.Close();
}
public static bool fileOpenForWriteOK(string writeFile, ref StreamWriter dataOut)
{
try
{
dataOut = new StreamWriter(writeFile);
return true;
}
catch (FileNotFoundException notFound)
{
MessageBox.Show("ERROR Opening file (when writing data out)" +
"- File could not be found.\n" + notFound.Message);
return false;
}
catch (Exception e)
{
MessageBox.Show("ERROR Opening File (when writing data out)" +
"- Operation failed.\n" + e.Message);
return false;
}
}
public static void writeSwitches()
{
StreamWriter outputSwitches = null;
if (fileOpenForWriteOK(inputDataFile, ref outputSwitches))
{
foreach (Switch currSwitch in switches)
{
outputSwitches.WriteLine(currSwitch.getSerialNo());
outputSwitches.WriteLine(currSwitch.getType());
outputSwitches.WriteLine(currSwitch.getInsDate());
outputSwitches.WriteLine(currSwitch.getElecTest());
outputSwitches.WriteLine(currSwitch.getPatId());
outputSwitches.WriteLine(currSwitch.getNumDevice());
}
outputSwitches.Close();
}
if (outputSwitches != null) outputSwitches.Close();
}
private void showListOfSwitches()
{
lstSwitch.Items.Clear();
foreach (Switch b in switches)
lstSwitch.Items.Add(b.getSerialNo()
+ b.getType() + b.getInsDate()
+ b.getElecTest() + b.getPatId() + b.getNumDevice());
}
My code for the search form:
private void btnSearch_Click(object sender, EventArgs e)
{
frmSearchSwitch tempSearchSwitch = new frmSearchSwitch();
tempSearchSwitch.Show();
frmkeepSwitches.Hide();
}
If using a List<T> and lambda is not possible for you then go no farther.
Here I use a List<T> for the data source of a ListBox and mocked up data as where the data comes from is not important but here I am focusing on searching on a property within a class where a select is used to index the items then the where searches in this case) for a specific item, if found the index is used to move to the item. No code present for if not located as this is easy for you to do if the code here is something that is doable for you.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace ListBoxSearch_cs
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Button1_Click(object sender, EventArgs e)
{
var results =
((List<Item>)ListBox1.DataSource)
.Select((data, index) => new
{ Text = data.SerialNumber, Index = index })
.Where((data) => data.Text == "BB1").FirstOrDefault();
if (results != null)
{
ListBox1.SelectedIndex = results.Index;
}
}
private void Form1_Load(object sender, EventArgs e)
{
var items = new List<Item>() {
new Item {Identifier = 1, SerialNumber = "AA1", Type = "A1"},
new Item {Identifier = 2, SerialNumber = "BB1", Type = "A1"},
new Item {Identifier = 3, SerialNumber = "CD12", Type = "XD1"}
};
ListBox1.DisplayMember = "DisplayText";
ListBox1.DataSource = items;
}
}
/// <summary>
/// Should be in it's own class file
/// but done here to keep code together
/// </summary>
public class Item
{
public string SerialNumber { get; set; }
public string Type { get; set; }
public int Identifier { get; set; }
public string DisplayText
{
get
{
return SerialNumber + " " + this.Type;
}
}
}
}

c# change color of sprites using a foreach loop

Hi guys i am beginner in C# programming and I need someone to explain me how I can change the colors of sprites. One said me that i can do this using a foreach loop however I get the same color red color:
The code:
using System;
using System.Text;
using System.Drawing;
using System.Threading.Tasks;
using Ionic.Zlib;
using Sulakore.Protocol;
using Sulakore.Extensions;
using Habbogram.Camera;
using Habbogram.Communication;
namespace Habbogram
{
public partial class MainFrm : ExtensionForm
{
private const string PREVIEW_IMAGE_BASE_URL = "https://habbo-stories-content.s3.amazonaws.com/";
private readonly Random _colorGenerator;
private TaskCompletionSource<bool> _wasReplacedAwaitable;
private readonly Action<HPhoto> _onCameraPayloadIntercepted;
public CameraTriggers GramTriggers { get; }
public HPhoto CurrentPhoto { get; private set; }
public override bool IsExternal { get; } = true;
public MainFrm()
{
InitializeComponent();
_colorGenerator = new Random();
_wasReplacedAwaitable = new TaskCompletionSource<bool>();
_onCameraPayloadIntercepted = OnCameraPayloadIntercepted;
GramTriggers = new CameraTriggers(true);
GramTriggers.DetectIncoming = false;
Triggers = GramTriggers;
GramTriggers.CameraPayload += GramTriggers_CameraPayload;
}
private void UpdateInterface(HPhoto photo)
{
bool isReplacing = (photo != null);
CancelBtn.Enabled = (ReplaceBtn.Enabled = isReplacing);
PlanesTab.Text = $"Planes({photo?.Planes.Count ?? 0})";
SpritesTab.Text = $"Sprites({photo?.Sprites.Count ?? 0})";
FiltersTab.Text = $"Filters({photo?.Filters.Count ?? 0})";
SpriteTxt.DataSource = photo?.Sprites;
SpriteTxt.Enabled = (photo != null);
}
private Color GenerateRandomColor(byte alpha)
{
byte a = alpha;
int r = _colorGenerator.Next(0, 126);
int g = _colorGenerator.Next(0, 126);
int b = _colorGenerator.Next(0, 126);
return Color.FromArgb(alpha, r, g, b);
}
private void OnCameraPayloadIntercepted(HPhoto photo)
{
if (InvokeRequired) Invoke(_onCameraPayloadIntercepted, photo);
else UpdateInterface(photo);
}
private void CancelBtn_Click(object sender, EventArgs e)
{
_wasReplacedAwaitable.SetResult(false);
UpdateInterface(null);
}
private void ReplaceBtn_Click(object sender, EventArgs e)
{
_wasReplacedAwaitable.SetResult(true);
UpdateInterface(null);
}
private void InterceptChckbx_CheckedChanged(object sender, EventArgs e)
{
if (InterceptChckbx.Checked)
{
GramTriggers.CameraPayload += GramTriggers_CameraPayload;
}
else
{
GramTriggers.CameraPayload -= GramTriggers_CameraPayload;
UpdateInterface(null);
}
}
private void GramTriggers_CameraPayload(object sender, CameraPayloadEventArgs e)
{
try
{
e.ContinueRead();
byte[] jsonPayload = ZlibStream.UncompressBuffer(e.JsonPayload);
string json = Encoding.UTF8.GetString(jsonPayload);
CurrentPhoto = HPhoto.Create(json);
OnCameraPayloadIntercepted(CurrentPhoto);
foreach (Camera.Layers.Sprite s in CurrentPhoto.Sprites)
{
//Set color for all sprites in the photo.
s.Color = Color.FromArgb(1, 255, 1, 1).ToArgb();
}
// Wait for user to invoke a 'replace'.
bool wasReplaced = _wasReplacedAwaitable.Task.Result;
if (!wasReplaced) return; // User cancelled.
json = CurrentPhoto.ToJson();
byte[] compressedJson = Encoding.UTF8.GetBytes(json);
compressedJson = ZlibStream.CompressBuffer(compressedJson);
e.Replacement = new HMessage(e.Packet.Header,
compressedJson.Length, compressedJson);
}
finally
{
// Create new instance, so that we don't wait for an already completed task.
_wasReplacedAwaitable = new TaskCompletionSource<bool>();
}
}
}
}
You have forgot to use call GenerateRandomColor() function. You can either call that function inside foreach loop or simply copy following code and paste it at place of your foreach loop. Upvote this answer if it satisfies.
foreach (Camera.Layers.Sprite s in CurrentPhoto.Sprites)
{
s.Color = Color.FromArgb(1, _colorGenerator.Next(1,256), _colorGenerator.Next(1,256), _colorGenerator.Next(1,256));
}
Also it seems that s.Color takes Color datatype...so you don't need to use .ToArgb(). However, if it does take int value, then do add .ToArgb() in the end of code.

C# Using SoundPlayer to Pause and Resume

I am another person dabbling with C# and wanting to create a simple audio application that plays wav files loaded into the program via an upload program. My issue is that I need to get whatever audio file currently being played to pause with the track timer of the audio file being used when I start the audio file again via my Play button. I already have a global timer, 'baseTimer', that I think I can use to set the audio file, that was stopped, track duration point. However I do not know how to accomplish this nor do I really know how to use all of the mci commands yet.
I have displayed all of my code for my main application... I also have read that I may need to utilize threading, but I've also read that it would be impossible to set an audio files track duration with a thread.
public partial class FrmMain : Form
{
public FrmMain()
{
InitializeComponent();
}
System.Timers.Timer baseTimer = new System.Timers.Timer();
List<string> PlayList = new List<string>();
List<byte> PlayList_byte;
int soundNum = 0;
private string music_PATH { get; set; }
private string talk_PATH { get; set; }
private byte Pause_TIME { get; set; }
private string Pause_RADIO { get; set; }
bool isStopped = new bool();
bool isPaused = new bool();
[DllImport("winmm.dll")]
private static extern uint mciSendString(string command, StringBuilder returnValue, int returnLength, IntPtr winHandle);
public static int GetSoundLength(string fileName)
{
StringBuilder lengthBuf = new StringBuilder(32);
mciSendString(string.Format("open \"{0}\" type waveaudio alias wave", fileName), null, 0, IntPtr.Zero);
mciSendString("status wave length", lengthBuf, lengthBuf.Capacity, IntPtr.Zero);
mciSendString("close wave", null, 0, IntPtr.Zero);
int length = 0;
int.TryParse(lengthBuf.ToString(), out length);
return length;
}
private void SetPath()
{
music_PATH = #"..\\..\\commercial\list.txt";
talk_PATH = #"..\\..\\main\list.txt";
StreamReader myReader;
using (myReader = new StreamReader(music_PATH))
{
while (myReader.Peek() != -1)
{
string read = myReader.ReadLine();
PlayList.Add(read);
}
}
using (myReader = new StreamReader(talk_PATH))
{
while (myReader.Peek() != -1)
{
string read = myReader.ReadLine();
PlayList.Add(read);
}
myReader.Close();
}
foreach (string sound in PlayList)
{
soundNum++;
}
}
private string CurrentSound()
{
try
{
Random _randx = new Random();
int pick = _randx.Next(0, soundNum);
string currentaudio = PlayList[pick];
Pause_RADIO = currentaudio;
return currentaudio;
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message);
}
return null;
}
string _SelectedSound = "";
private string _Sound(string currentradio, string pattern)
{
foreach (Match entry in Regex.Matches(currentradio, pattern))
{
_SelectedSound = entry.Value.ToString();
}
if (_SelectedSound == "music")
{
return "commercial";
}
else if (_SelectedSound == "talk")
{
return "main";
}
return null;
}
private void _SetTimer(string currentradio, string pattern)
{
baseTimer.Interval = GetSoundLength(#"..\\..\\" + pattern + #"\" + currentradio);
}
private bool isRepeat(string lastradio, string currentradio)
{
if (lastradio == currentradio)
{
return true;
}
else
{
return false;
}
}
private void baseTimerElasped(object sender, ElapsedEventArgs e)
{
Radio.FrmMain play = new Radio.FrmMain();
play.PlayPlayer();
}
private void PlayPlayer()
{
MediaPlayer wavplayer;
try
{
if (soundNum == 0)
{
SetPath();
PlayPlayer();
}
else
{
string currentradio = CurrentSound();
bool localcheck = isRepeat(_SelectedSound, currentradio);
if (localcheck == true)
{
PlayPlayer();
}
else
{
string Pattern = #"(music|talk)";
string selected = _Sound(currentradio, Pattern);
_SetTimer(currentradio, selected);
switch (selected)
{
case "commercial":
music_PATH = #"..\\..\\commercial\";
PlayList_byte = new List<byte>(File.ReadAllBytes(music_PATH + currentradio));
wavplayer = new MediaPlayer(PlayList_byte.GetRange(0, PlayList_byte.Count).ToArray());
wavplayer.Play();
baseTimer.Start();
break;
case "main":
talk_PATH = #"..\\..\\main\";
PlayList_byte = new List<byte>(File.ReadAllBytes(talk_PATH + currentradio));
wavplayer = new MediaPlayer(PlayList_byte.GetRange(0, PlayList_byte.Count).ToArray());
wavplayer.Play();
baseTimer.Start();
break;
}
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message + ex.StackTrace + ex.Source);
}
}
private void PausePlayer()
{
MediaPlayer wavplayer = new MediaPlayer(PlayList_byte.GetRange(0, PlayList_byte.Count).ToArray());
baseTimer.Stop();
MessageBox.Show("Count: " + PlayList_byte.Count + "Pause_TIME: " + Pause_TIME + "\nPlaylist_byte" + PlayList_byte.ToString());
try
{
switch (isPaused)
{
case false:
isPaused = true;
wavplayer.Stop();
break;
case true:
isPaused = false;
string localcheck = _Sound(Pause_RADIO, #"(music|talk)");
switch (localcheck)
{
case "commercial":
music_PATH = #"..\\..\\commercial\";
wavplayer.Play(PlayList_byte.GetRange(PlayList_byte.Count - Pause_TIME, PlayList_byte.Count - Pause_TIME).ToArray());
break;
case "main":
talk_PATH = #"..\\..\\main\";
wavplayer.Play(PlayList_byte.GetRange(PlayList_byte.Count - Pause_TIME, PlayList_byte.Count - Pause_TIME).ToArray());
break;
}
break;
}
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message + ex.Data);
}
}
private void btnPlay_Click(object sender, EventArgs e)
{
switch (isStopped)
{
case false:
isStopped = true;
btnPlay.Image = Image.FromFile(#"..\\..\\Pause.png");
lblPlay.Text = "Pause";
if (isPaused == false)
{
PlayPlayer();
}
else
{
PausePlayer();
}
break;
case true:
isStopped = false;
btnPlay.Image = Image.FromFile(#"..\\..\\Play.png");
lblPlay.Text = "Play";
PausePlayer();
break;
}
baseTimer.Elapsed += new ElapsedEventHandler(baseTimerElasped);
}
private void btnNext_Click(object sender, EventArgs e)
{
PlayPlayer();
}
private void btnStop_Click(object sender, EventArgs e)
{
MediaPlayer wavplayer = new MediaPlayer();
wavplayer.Stop();
baseTimer.Stop();
}
private void btnQuit_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void btnGetUpload_Click(object sender, EventArgs e)
{
Uploader FrmUpload = new Uploader();
FrmUpload.Show();
this.Hide();
}
}
class MediaPlayer
{
SoundPlayer wavplayer;
public MediaPlayer()
{
Stop();
}
public MediaPlayer(byte[] buffer)
{
MemoryStream memStream = new MemoryStream(buffer, true);
wavplayer = new SoundPlayer(memStream);
}
public void Play()
{
wavplayer.Play();
}
public void Play(byte[] buffer)
{
wavplayer.Stream.Seek(0, SeekOrigin.Begin);
wavplayer.Stream.Write(buffer, 0, buffer.Length);
wavplayer.Play();
}
public void Stop()
{
wavplayer.Stop();
}
}
Edit:
For clarity currentaudio has a file as such "music3.wav" or "talk1.wav" in it.
Super old question but just for anyone looking here's what worked for me:
double currentPos = audioplayer.CurrentPosition;
audioplayer.Play();
audioplayer.Seek(currentPos);
SoundPlayer is extremely limited, and doesn't support Pause and Resume. Are you able to use the WPF MediaElement instead? You will find it is much more powerful, supporting playing files of many types, repositioning, setting volume, pausing and resuming. You can also use it to get the file length instead of mci.

Why the number of threads is continuously increasing with SerialPort.CatchReceivedEvents()

I´m running a C# application with .NET Framework 2.0 to read data from SerialPort to get the weight from a scale.
The application works fine, does what it is supposed to do, but the number of threads keeps increasing and more memory is consumed until the application crashes, usually after around 4 hours.
When running with a serialport simulator the number of threads is stable around 30. But when I use an actual scale it goes greater than 500 threads.
I used Microsoft Managed Stack Explorer 1.0 to take a dump of the threads and almost all of them have exactly the following stack:
0. System.IO.Ports.SerialPort.CatchReceivedEvents (Source Unavailable)
1. System.IO.Ports.SerialStream.EventLoopRunner.CallReceiveEvents (Source Unavailable)
2. System.Threading._ThreadPoolWaitCallback.WaitCallback_Context (Source Unavailable)
3. System.Threading.ExecutionContext.Run (Source Unavailable)
4. System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal (Source Unavailable)
5. System.Threading._ThreadPoolWaitCallback.PerformWaitCallback (Source Unavailable)
I'm not able to identify the reason these threads are being created. Does anybody have any idea of what I'm missing here? Thanks!
This is my code:
Scale.cs -> creates a thread when method open() is called. The thread reads the value from getWeight().
Scales.cs -> treats events from serial port in method SerialPort_DataReceived(...). It's where m_SerialPort.ReadLine() is called and ends up providing the value to getWeight().
Scale.cs:
using System;
using System.Collections.Generic;
using System.Threading;
using ScalesGSS;
using StateMachine.Exceptions;
using StateMachine.Log;
using StateMachine.MessageOutput;
namespace StateMachine.DriverImplementation
{
class Scale : AScale
{
private const int Scale_version = 1;
private Thread thread = null;
private IScales gScale = null;
//
private string m_Type;
private string m_PortName;
private int m_BaudRate;
private char m_Parity;
private int m_DataBits;
private string m_StopBits;
private int m_CommandReturnLength;
private string m_CommandType;
private string m_CommandValue;
private int m_ReadTimeOutInMilliseconds;
private int m_WeightInitialPosition;
private int m_WeightFinalPosition;
private int m_TimeBetweenReadsInMilliseconds;
private int m_StableReadQuantity;
private int m_MinimumWeight;
private int m_ScaleID;
//
private double m_OldWeight = 0.0;
private double m_Offset = 0.0;
private double m_CurrentWeight = 0.0;
int m_WeightEqualCount = 0;
//
byte m_Status = 3; // "NO COMMUNICATION"
//
private bool m_Closed = false;
private static LogFactory m_Log = new LogFactory(LogCategory.Device, "");
ErrorDialog m_ErrorDialog = new ErrorDialog();
public Scale()
{
this.setClassName("Scale");
this.setDeviceType(DeviceType.Scale);
}
public void run()
{
try
{
if (this.m_Type.ToUpper().Equals("GENERICSCALES")) // GENERICSCALES or MOCKSCALES
this.gScale = new ScalesGSS.GenericScales();
else
this.gScale = new ScalesGSS.MockScales();
this.gScale.PortName = this.m_PortName;
this.gScale.BaudRate = this.m_BaudRate;
this.gScale.Parity = this.m_Parity.ToString();
this.gScale.DataBits = this.m_DataBits;
this.gScale.StopBits = this.m_StopBits;
this.gScale.CommandReturnLength = this.m_CommandReturnLength;
this.gScale.CommandType = this.m_CommandType;
this.gScale.CommandValue = this.m_CommandValue;
this.gScale.ReadTimeOut = this.m_ReadTimeOutInMilliseconds;
this.gScale.WeightInitialPosition = this.m_WeightInitialPosition;
this.gScale.WeightFinalPosition = this.m_WeightFinalPosition;
this.gScale.setParameters();
this.gScale.configurePort();
while (true)
{
if (this.m_Closed)
{
if (this.OpenedPort())
this.gScale.closePort();
break;
}
Thread.Sleep(this.m_TimeBetweenReadsInMilliseconds);
if (!this.OpenedPort())
{
if (!this.OpenPort())
{
m_Log.writeLogWarning("Error opening serialport.", " Port: " + this.m_PortName, true);
}
}
if (this.ErrorReadingWeight())
{
m_Log.writeLogWarning("Invalid weight.", " Port: " + this.m_PortName, true);
}
this.m_CurrentWeight = getWeight();
if (!ReadingTimeout())
{
if (this.m_WeightEqualCount > m_StableReadQuantity)
{
if (m_CurrentWeight > m_MinimumWeight)
m_Status = 2; // "WEIGHT STABLE"
else
{
m_Status = 0; // "SCALE FREE"
m_WeightEqualCount = 0;
}
}
else
{
if (m_CurrentWeight > m_MinimumWeight)
{
m_Status = 1; // "STABILIZING"
if ((this.m_CurrentWeight >= (this.m_OldWeight - this.m_Offset)) && (this.m_CurrentWeight <= (this.m_OldWeight + this.m_Offset)))
this.m_WeightEqualCount++;
else
this.m_WeightEqualCount = 0;
this.m_OldWeight = this.m_CurrentWeight;
}
else
{
m_Status = 0; // "SCALE FREE"
m_WeightEqualCount = 0;
}
}
}
else
{
m_WeightEqualCount = 0;
m_Status = 3; // "NO COMMUNICATION"
string v_Message = "No communication with scale. Port: " + m_PortName;
m_Log.writeLogWarning(v_Message, "", true);
AutoClosingMessageBox.Show(v_Message, "Scale", 10000);
}
}
}
catch (Exception v_Exception)
{
m_Log.writeLogError("run()", v_Exception);
}
}
private bool OpenedPort()
{
return this.gScale.OpenedPort;
}
private bool OpenPort()
{
bool v_OpenPort;
v_OpenPort = this.gScale.openPort();
if (!v_OpenPort)
{
m_ErrorDialog.getScaleErrorMessage(gScale);
}
return v_OpenPort;
}
private bool ErrorReadingWeight()
{
return this.gScale.ErrorReadingWeight;
}
private double getWeight()
{
return this.gScale.getWeight();
}
private DateTime LastGoodReading()
{
return gScale.LastGoodReading;
}
private void setLastGoodReading(DateTime p_Value)
{
gScale.LastGoodReading = p_Value;
}
private bool ReadingTimeout()
{
if (m_ReadTimeOutInMilliseconds > 0)
{
DateTime v_LastGoodReading = LastGoodReading() == DateTime.MinValue ? DateTime.Now : LastGoodReading();
setLastGoodReading(DateTime.Now);
return DateTime.Now > v_LastGoodReading.AddMilliseconds(m_ReadTimeOutInMilliseconds);
}
else
return false;
}
#region "IDriverService"
public override byte getStatus()
{
return m_Status;
}
public override byte[] read()
{
return System.Text.ASCIIEncoding.ASCII.GetBytes(m_CurrentWeight.ToString());
}
public override byte[] read(int p_InitialPosition, int p_Size)
{
return read();
}
public override byte[] write(byte[] p_Data)
{
string v_Temp = System.Text.ASCIIEncoding.ASCII.GetString(p_Data);
if (v_Temp.Equals("getScaleNumber"))
return System.Text.ASCIIEncoding.ASCII.GetBytes(m_ScaleID.ToString());
else
throw new EDriverAccess(1, "Not implemented");
}
public override bool open()
{
this.thread = new Thread(run);
this.thread.Name = "SCALE";
this.thread.IsBackground = true;
this.thread.Start();
return true;
}
public override bool close()
{
try
{
this.release();
return true;
}
catch
{
return false;
}
}
public override int getVersion()
{
return Scale_version;
}
public override void setProperties(Dictionary<string, string> p_props)
{
try
{
this.m_Type = p_props["type"];
this.m_PortName = p_props["portName"];
this.m_BaudRate = Int32.Parse(p_props["baudRate"]);
this.m_Parity = char.Parse(p_props["parity"]);
this.m_DataBits = Int32.Parse(p_props["dataBits"]);
this.m_StopBits = p_props["stopBits"];
this.m_CommandReturnLength = Int32.Parse(p_props["returnLength"]);
this.m_CommandType = p_props["commandType"];
this.m_CommandValue = p_props["commandValue"];
this.m_ReadTimeOutInMilliseconds = Int32.Parse(p_props["readTimeout"]);
this.m_WeightInitialPosition = Int32.Parse(p_props["weightInitPos"]);
this.m_WeightFinalPosition = Int32.Parse(p_props["weightFinPos"]);
this.m_TimeBetweenReadsInMilliseconds = Int32.Parse(p_props["delayLeitura"]);
this.m_StableReadQuantity = Int32.Parse(p_props["qtdeLeituraEstavel"]);
this.m_MinimumWeight = Int32.Parse(p_props["pesoMinimo"]);
this.m_ScaleID = Int32.Parse(p_props["numBalanca"]);
if (p_props.ContainsKey("precision"))
this.m_Offset = Int32.Parse(p_props["precision"]);
}
catch (Exception)
{
throw new Exception();
}
}
public override void release()
{
this.m_Closed = true;
m_Status = 3; // "NO COMMUNICATION"
}
#endregion
}
}
Scales.cs:
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Reflection;
using System.Timers;
using Scales.Util;
namespace Scales.DLL
{
public class Scales : Status
{
public event EventHandler StableWeightChanged;
protected virtual void OnCountdownCompleted(EventArgs e)
{
if (StableWeightChanged != null)
StableWeightChanged(this, e);
}
System.Timers.Timer timerTimeWithoutSample;
private int m_IntervalsWithoutSample = 0;
private string m_EndOfWeightChar = "";
private void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
m_IntervalsWithoutSample++;
}
public int IntervalsWithoutSample { get { return m_IntervalsWithoutSample; } }
private SerialPort m_SerialPort;
public string PortName { get; set; }
public int BaudRate { get; set; }
public int DataBits { get; set; }
private Double m_Weight = 0;
public Double Weight
{
get
{
if (m_BufferWeights.Count > 0)
{
try
{
m_Weight = treatReceivedValue(m_BufferWeights[m_BufferWeights.Count - 1]);
}
catch
{
}
finally
{
ErrorReadingWeight = (m_Weight != -1 ? false : true);
}
}
else
{
m_Weight = 0;
}
return m_Weight;
}
}
public List<Double> getAndFlushPastWeights()
{
List<Double> v_FlushedValues = new List<double>();
Double v_WeightCursor;
while (m_BufferWeights.Count > 1 && v_FlushedValues.Count < 200)
{
v_WeightCursor = treatReceivedValue(m_BufferWeights[0]);
if (v_WeightCursor >= 0)
{
v_FlushedValues.Add(v_WeightCursor);
}
m_BufferWeights.RemoveAt(0);
}
return v_FlushedValues;
}
public void ResetWeights()
{
if (m_BufferWeights != null)
{
m_BufferWeights.Clear();
}
}
public string NewLineCommandType { get; set; }
public string NewLineCommand { get; set; }
public int ReturnLength { get; set; }
public int WeightInitialPosition { get; set; }
public int WeightFinalPosition { get; set; }
public int MotionBitPos { get; set; }
public int ReadTimeOut { get; set; }
public bool OpenedPort { get; private set; }
public bool ErrorReadingWeight { get; private set; }
public DateTime LastGoodReading { get; private set; }
public bool IsStable { get; private set; }
private Parity PortParity { get; set; }
public string SerialParity
{
get { return PortParity.ToString(); }
set
{
setParity(value);
}
}
public int WeightReadLength
{
get
{
if (WeightFinalPosition >= WeightInitialPosition)
{
return WeightFinalPosition - WeightInitialPosition + 1;
}
else
{
return 0;
}
}
}
private StopBits PortStopBits { get; set; }
public string SerialStopBits
{
get { return PortStopBits.ToString(); }
set
{
setStopBits(value);
}
}
private void setParity(string p_Parity)
{
if (p_Parity.Equals(Parity.Even.ToString()))
{
PortParity = Parity.Even;
}
else if (p_Parity.Equals(Parity.Mark.ToString()))
{
PortParity = Parity.Mark;
}
else if (p_Parity.Equals(Parity.Odd.ToString()))
{
PortParity = Parity.Odd;
}
else if (p_Parity.Equals(Parity.Space.ToString()))
{
PortParity = Parity.Space;
}
else
{
PortParity = Parity.None;
}
}
private void setStopBits(string p_StopBits)
{
if (p_StopBits.Equals(StopBits.One.ToString()))
{
PortStopBits = StopBits.One;
}
else if (p_StopBits.Equals(StopBits.OnePointFive.ToString()))
{
PortStopBits = StopBits.OnePointFive;
}
else if (p_StopBits.Equals(StopBits.Two.ToString()))
{
PortStopBits = StopBits.Two;
}
else if (p_StopBits.Equals("1"))
{
PortStopBits = StopBits.One;
}
else if (p_StopBits.Equals("1.5"))
{
PortStopBits = StopBits.OnePointFive;
}
else if (p_StopBits.Equals("2"))
{
PortStopBits = StopBits.Two;
}
else
{
PortStopBits = StopBits.None;
}
}
public Scales()
{
OpenedPort = false;
ErrorReadingWeight = false;
IsStable = false;
m_IntervalsWithoutSample = 999999;
timerTimeWithoutSample = new System.Timers.Timer(5);
timerTimeWithoutSample.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
}
private int ignoreNextXValues;
public void resetScale()
{
ErrorReadingWeight = false;
IsStable = false;
m_IntervalsWithoutSample = 999999;
ignoreNextXValues = 2;
m_BufferWeights.Clear();
m_BufferTime.Clear();
if (m_SerialPort != null && m_SerialPort.IsOpen)
{
m_SerialPort.Close();
m_SerialPort.Open();
m_SerialPort.DiscardInBuffer();
}
}
List<String> m_BufferWeights = new List<String>();
List<String> m_BufferTime = new List<String>();
public bool openPort()
{
try
{
if (m_SerialPort.IsOpen)
{
m_SerialPort.Close();
}
m_SerialPort.Open();
resetScale();
OpenedPort = true;
return true;
}
catch (Exception ex)
{
MessageDetail = ex.Message;
Return = -100;
OpenedPort = false;
return false;
}
}
public bool closePort()
{
try
{
if (m_SerialPort != null)
{
if (m_SerialPort.IsOpen)
{
m_SerialPort.Close();
}
}
OpenedPort = false;
return true;
}
catch (Exception ex)
{
MessageDetail = ex.Message;
Return = -101;
return false;
}
}
public bool configurePort()
{
try
{
m_SerialPort = new SerialPort();
m_SerialPort.PortName = PortName;
m_SerialPort.BaudRate = BaudRate;
m_SerialPort.Parity = PortParity;
m_SerialPort.DataBits = DataBits;
m_SerialPort.StopBits = PortStopBits;
m_SerialPort.ReadTimeout = ReadTimeOut > 0 ? ReadTimeOut : SerialPort.InfiniteTimeout;
m_SerialPort.NewLine = getNewLineCommand();
m_SerialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived);
return true;
}
catch (Exception ex)
{
MessageDetail = ex.Message;
Return = -102;
return false;
}
}
private string getNewLineCommand()
{
string v_Command = string.Empty;
if (NewLineCommandType.ToUpper().Equals(CommandTypes.CHAR.ToUpper()))
{
byte v_Char = Convert.ToByte(NewLineCommand);
v_Command = Convert.ToChar(v_Char).ToString();
}
else if (NewLineCommandType.ToUpper().Equals(CommandTypes.STRING.ToUpper()))
{
v_Command = NewLineCommand;
}
else
{
char[] v_delimiters = { '|' };
String[] v_Strings = NewLineCommand.Split(v_delimiters);
if (v_Strings.Length == 2)
{
v_Command = v_Strings[0];
m_EndOfWeightChar = v_Strings[1];
}
else
{
v_Command = NewLineCommand;
}
}
return v_Command;
}
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
LastGoodReading = DateTime.Now;
string ReadLine = m_SerialPort.ReadLine();
m_BufferWeights.Add(ReadLine);
}
catch (Exception)
{
m_Weight = 0;
LastGoodReading = DateTime.MinValue;
}
}
private Double treatReceivedValue(string p_ReceivedValue)
{
try
{
if (ignoreNextXValues > 0) ignoreNextXValues--;
if (ignoreNextXValues > 0) return 0;
double v_Value = double.MinValue;
p_ReceivedValue = p_ReceivedValue.Replace("\r", "").Replace("\n", "");
m_IntervalsWithoutSample = 0;
if (p_ReceivedValue.Length < WeightInitialPosition + WeightReadLength)
{
return -1;
}
if (MotionBitPos != -1 && p_ReceivedValue.Length < MotionBitPos - 1)
{
return -1;
}
string strValor = "";
if (NewLineCommandType.ToUpper().Equals(CommandTypes.VARIABLE_LENGTH.ToUpper()))
{
int v_EndCharPos = p_ReceivedValue.IndexOf(m_EndOfWeightChar);
if (v_EndCharPos != -1)
{
strValor = p_ReceivedValue.Substring(0, v_EndCharPos).Trim();
}
}
else
{
strValor = p_ReceivedValue.Substring(WeightInitialPosition, WeightReadLength).Trim();
}
bool IsDouble = double.TryParse(strValor, out v_Value);
if (IsDouble)
{
if (MotionBitPos != -1)
{
string bit = p_ReceivedValue.Substring(MotionBitPos, 1).Trim();
if (bit == "1")
{
IsStable = true;
}
else IsStable = false;
}
else
{
IsStable = true;
}
return v_Value;
}
else
{
return -1;
}
}
catch (Exception ex)
{
Return = -200;
MessageDetail = ex.Message + " - Fonte:readScales";
ErrorReadingWeight = true;
}
return -1;
}
}
}
I had a similar problem, using SerialPort.ReadExisting() insted of SerialPort.ReadLine() I was able to avoid the creation of infinite threads.
You should try to reduce your problematic code down to something more manageable, as it will make it easier for others to debug. There's a lot of application logic in there that's probably not relevant to the problem which can make it hard for people to see what's going on. You'll get a lot more answers if your example is shorter. You may even figure the problem out yourself in the process!
Having said that, I have a hunch about what's wrong but you'll need to do a little bit of the leg-work yourself to discover if I'm right or wrong:
The .NET serial port works by waiting for data to come in, and then firing the DataReceived event on a worker thread whenever it notices that there's new data. I believe you have 400 or 500 of these worker threads that never complete their work, so they never go away.
Your event handler for the SerialPort.DataReceived event looks like it's blocking waiting for a whole line to come in, but the event is going to be fired whenever there's some amount of new data on the serial port (not necessarily a whole line). If a long line of text comes in, the DataReceived event is going to fire many times, each on it's own worker thread. These worker threads are synchronized to each other, so they're all going to wait for the previous one to finish.
The first thread that gets queued up is going to wait for a while at m_SerialPort.ReadLine() until the whole line comes in.
A bunch of threads queue up behind the first thread as more characters come in. The rest of the threads will end up waiting for the first thread to finish running your event handler.
Finally, the whole line comes in. The first thread finishes, and one of the 5 or 6 that are queued up behind it gets to run and the process starts all over.
The running thread blocks on ReadLine, 5 or 6 more queue up behind it. (We're now back at 1)
Eventually you have so many threads queued up that you run into memory issues.
You probably have the read-timeout on m_SerialPort set to timeout.Infinite. If you set the timeout to something smaller, like 1 second (1000) and you get a lot of TimeoutExceptions in your SerialPort_DataReceived method, then I'm probably right
Side Note You should catch a more specific exception type in your DataReceived event handler. Catching exception can mask exactly this type of problem.
If I've correctly diagnosed the problem, you'll need to change the architecture of your program a little bit. The simplest thing to do is not subscribe to the DataReceived event and to have a single worker thread call m_SerialPort.ReadLine(); with an infinite timeout. When it reads a line, have that worker thread raise an event with the whole line of text received and subscribe to THAT event instead of the SerialPort.DataReceived(); event.
Alternatively, if you want to subscribe to the SerialPort.DataReceived(); event, then read individual characters out of the SerialPort until SerialPort.BytesToRead is zero and stick them in a buffer. Then, when you have a whole line raise some "LineReceived" event that you make yourself that returns the whole line at once as one of the EventArgs. This method is doesn't require you to spool up your own thread that persists for a really long time.

Emulating console in winforms, the hard way how to make it better

Im trying to emulate the console in a windows forms applicaton. I have made it possible by using two extra threads and a delegate to be able to interact with my multiline textbox.
This somehow seems like I complicate things to much. So my questions.
Is there a better way of doing this?
When i press enter the command does not get sent, first if i press again it get sent? WHy is that? I ahve treid to debug it but failed to find the solution.
EDIT! Im using CsharpSSH, to do the SSH connection. Also I have included my full code now!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Tamir.SharpSsh;
using System.IO;
using System.Threading;
using System.Timers;
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
public string mHost;
SshShell mShell;
public string mInput;
string pattern = "";
bool mInputHolder = false;
string mPattern = "";
int mValue = 0;
bool mStatus = false;
private Thread thrdtwo = null;
private Thread thrdone = null;
public string mKorv;
string mString = "";
delegate void SetTextCallback(string text);
bool clientopen = true;
public Form1()
{
InitializeComponent();
txthost.Text = "sdf.org";
txtuser.Text = "kalle82";
txtpass.Text = "kattsand";
string pattern = "sdf:";
mPattern = pattern;
}
public void button1_Click(object sender, EventArgs e)
{
mShell = new SshShell(Host, User);
mShell.Password = Pass;
//WRITING USER MESSAGE
txtOutput.AppendText("Connecting...");
mShell.Connect();
txtOutput.AppendText("OK");
mShell.ExpectPattern = mPattern;
mShell.RemoveTerminalEmulationCharacters = true;
this.SetText(mShell.Expect(pattern));
txtInput.Focus();
thrdone = new Thread(new ThreadStart(appengine));
thrdone.Start();
}
private void appengine()
{
this.txtInput.KeyPress += new System.Windows.Forms.KeyPressEventHandler(checkforenter);
// MessageBox.Show("Appengine started");
while (mShell.ShellOpened)
{
thrdtwo = new Thread(new ThreadStart(startthread2));
thrdtwo.Start();
thrdtwo.Join();
// this.SetText(mShell.Expect(pattern));
if (clientopen == false) break;
}
// MessageBox.Show("Appengine stopped");
}
private void startthread2()
{
//Wait for answer
while (mStatus == false)
{
}
}
//Recieves keypressevent
public void checkforenter(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
if (e.KeyChar == (char)13)
{
mStatus = true;
mString = txtInput.Text;
mShell.WriteLine(mString);
this.SetText(mShell.Expect(pattern));
txtOutput.AppendText(txtInput.Text + "\n");
}
mStatus = false;
}
private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.txtOutput.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.txtOutput.Text = text.ToString();
}
}
public int checkfortrue()
{
if (mInputHolder != true)
{
mValue = 0;
}
if (mInputHolder == false)
{
mValue = -1;
}
return mValue;
}
public string userInput()
{
while (mInputHolder == true)
{
}
mInputHolder = true;
return txtInput.Text;
}
//Properties
public string Host
{
get
{
return txthost.Text;
}
set
{
txthost.Text = value;
}
}
public string User
{
get
{
return txtuser.Text;
}
set
{
txtuser.Text = value;
}
}
public string Pass
{
get
{
return txtpass.Text;
}
set
{
txtpass.Text = value;
}
}
public string Pattern
{
get
{
return pattern;
}
set
{
pattern = value;
}
}
private void button2_Click(object sender, EventArgs e)
{
clientopen = false;
}
}
}

Categories