I'm doing a program for serial communications. To centralize the process of access to serial, created a class.
I am having problem when an exception is lançanda within the class leaves the locked program.
example:
When trying aberir the serial port, can give error and the system is at that point to burst memory.
How should I handle errors?
Put try and catch?
Add another routine?
Error point:
portSerial.Open();
Program
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 PortSerial.Lib;
namespace ProgramPortSerial
{
public partial class Form1 : Form {
public static LibPortaSerial portSerial = new LibPortSerial();
public Form1()
{
InitializeComponent();
portSerial.LineReceived += new LineReceivedEventHandler(sp1_LineReceived);
portSerial.Init(
ref cmbPortas,
ref cmbVelocidade,
ref cmbBitsDeDados,
ref cmbPariedade,
ref cmbBitsDeParada,
ref cmbControleDeFluxo);
}
void sp1_LineReceived(object sender, LineReceivedEventArgs Args)
{
// Tem que ser em uma nova thread para não travar
Invoke(new Action(() =>
{
memDadosRecebidos.Text += "\r\n" + Args.Resposta;
}));
}
private void btnAbrirPorta_Click(object sender, EventArgs e)
{
portSerial.Open();
}
}
}
Class PortSerial
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Windows.Forms;
namespace PortSerial.Lib
{
public class LibPortSerial : IDisposable
{
public SerialPort portSerial;
public LibPortSerial()
{
portSerial = new SerialPort();
}
public void Dispose()
{
if (portSerial != null)
portSerial.Dispose();
}
public void Open(
string port,
int veloc,
int bitsData,
string pariedade,
string bitsStop,
string control)
{
portSerial.PortName = port;
portSerial.BaudRate = veloc;
portSerial.DataBits = bitsData;
portSerial.Parity = SetPariedade(pariedade);
portSerial.StopBits = SetBitsStop(bitsStop);
portSerial.Handshake = Setcontrol(control);
portSerial.Open(); // ==> Erro this point
}
}
}
You should write it as:
public void Open(
string port,
int veloc,
int bitsData,
string pariedade,
string bitsStop,
string control)
{
portSerial.PortName = port;
portSerial.BaudRate = veloc;
portSerial.DataBits = bitsData;
portSerial.Parity = SetPariedade(pariedade);
portSerial.StopBits = SetBitsStop(bitsStop);
portSerial.Handshake = Setcontrol(control);
try
{
portSerial.Open(); // ==> Erro this point
}
catch(IOException exp)
{
return exp.Message;
}
}
Related
My aim is to save the all form data via button click (as opposed to upon closing). To that end, I've used the example given in the following thread. Saving the form state then opening it back up in the same state
I've tried to adapt my code to the best of my ability, but nothing happens, and there are no errors shown. What am I doing wrong?
Here's the relevant parts of my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Serialization;
namespace WindowsFormsApplication1
{
public partial class frmPayroll : Form
{
SaveData sd = new SaveData();
public frmPayroll()
{
InitializeComponent();
}
private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{
writeConfig();
}
private void writeConfig()
{
using (StreamWriter sw = new StreamWriter("config.xml"))
{
sd.Married = rdoMarr.Checked;
sd.PayPd = cbPayPd.Text;
sd.Allow = cbAllow.Text;
sd.Gross = txtGross.Text;
sd.Fit = txtFit.Text;
sd.Soc = txtSoc.Text;
sd.Med = txtMed.Text;
sd.NetPay = txtNet.Text;
sd.PayPd = cbPayPd.Text;
XmlSerializer ser = new XmlSerializer(typeof(SaveData));
ser.Serialize(sw, sd);
}
}
private void frmPayroll_Load(object sender, EventArgs e)
{
if (File.Exists("config.xml"))
{
loadConfig();
}
sd.Married = rdoMarr.Checked;
sd.PayPd = cbPayPd.Text;
sd.Allow = cbAllow.Text;
sd.Gross = txtGross.Text;
sd.Fit = txtFit.Text;
sd.Soc = txtSoc.Text;
sd.Med = txtMed.Text;
sd.NetPay = txtNet.Text;
}
private void loadConfig()
{
XmlSerializer ser = new XmlSerializer(typeof(SaveData));
using (FileStream fs = File.OpenRead("config.xml"))
{
sd = (SaveData)ser.Deserialize(fs);
}
}
}
public struct SaveData
{
public bool Married;
public string PayPd;
public string Allow;
public string Gross;
public string Fit;
public string Soc;
public string Med;
public string NetPay;
}
}
You are loading your object by deserializing.
But Where are you assigning the states back to your controls?
look at frmPayroll_Load function.
You are trying to assign the data back to the object again.
You have to assign data back to form controls.
Should be something like this (you may need to apply data conversions if required):
rdoMarr.Checked = sd.Married;
.
.
.
.
txtFit.Text = sd.Fit;
.
.
.
.
I'm doing some test using the .NET 4.5 TestTools and Visual Studio 2010. I m testing a singleton class that creates an COM Instance somewhere during construction/initialization, so the classes state will be keep the same in all tests. The Problem is, each test runs for itself, running all test will give a strange result - the first test succeeds, all other fail
"System.Runtime.InteropServices.InvalidComObjectException: COM object
that has been separated from its underlying RCW cannot be used.."
result of a corrupted COM reference (see myComInstance below).
Not quite sure if i explained the problem correctly. Below is my singleton class
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;
namespace APITestTrial3
{
public partial class frmMbxControl : Form
{
private frmMbxControl()
{
InitializeComponent();
Connect("abhishek281mbx","PCMBXsrv.281","appmat1.bsd.com");
}
private static frmMbxControl g_Mbx;
public static frmMbxControl GetMbx()
{
if (g_Mbx == null)
{
g_Mbx = new frmMbxControl();
}
return g_Mbx;
}
private string Connect(string mbxName, string serverName, string hostName)
{
// frmControls frm = new frmControls();
mbx.HostName = hostName;
mbx.MbxName = mbxName;
mbx.ServerName = serverName;
mbx.replybox = "replyBox";
if (mbx.Status != 0)
{
if (mbx.Connect())
{
Console.WriteLine("Connected");
return ("Connected");
}
else
{
return ("Not Connected");
}
}
return ("Connected");
}
public String Send(String txnName, String txn)
{
String msgReply = "";
String rep = "";
//mbx.Send(txnName, txn);
mbx.Open("ReplyBox1","c");
mbx.SendAndReply(txnName, txn, "ReplyBox1");
if (mbx.WaitForMsg("ReplyBox1", 0, ref msgReply, ref rep) == CwMboxLib.CwWaitResult.CwWaitOk)
{
rep = msgReply;
mbx.Close("ReplyBox1");
}
return msgReply;
}
private void frmMbxControl_Load(object sender, EventArgs e)
{
}
}
}
Another class uses GetMbx() and Send() method of above class.
I keep getting this error and I know why but I need help figuring out how I can solve it. The only way I have been able to add my items it to make a new form but that seems silly.
It wont work if I make all my methods static =(
I keep getting,
"An object reference is required for the non-static field, method, or
property 'Handicap_Calculator.FormMain.listViewLog'
\Form1.cs 74 13 Handicap Calculator"
Here´s my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Handicap_Calculator
{
public partial class FormMain : Form
{
//FormAddScore FormAddNewScore = new FormAddScore();
public static bool addScoreIsShown = false;
public static FormAddScore _FormAddScore;
public static ListViewItem Item;
//public static List<string> ScoreInfo = new List<string>();
public FormMain()
{
InitializeComponent();
}
public void button1_Click(object sender, EventArgs e)
{
try
{
if (_FormAddScore == null || _FormAddScore.IsDisposed)
{
_FormAddScore = new FormAddScore();
}
_FormAddScore.Show();
if (_FormAddScore.WindowState == FormWindowState.Minimized)
{
_FormAddScore.WindowState = FormWindowState.Normal;
}
_FormAddScore.BringToFront();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
public static void AddScore()
{
int Round = 1;
DateTime date = _FormAddScore.date;
string course = _FormAddScore.course;
int holes = _FormAddScore.holes;
int score = _FormAddScore.score;
float courseRating = _FormAddScore.courseRating;
float slopeRating = _FormAddScore.slopeRating;
string[] ScoreInfo = new string[7];
ScoreInfo[0] = Round.ToString();
ScoreInfo[1] = date.ToString();
ScoreInfo[2] = course;
ScoreInfo[3] = holes.ToString();
ScoreInfo[4] = score.ToString();
ScoreInfo[5] = courseRating.ToString();
ScoreInfo[6] = slopeRating.ToString();
AddToList(ScoreInfo);
}
public static void AddToList(string[] ScoreInfo)
{
Item = new ListViewItem(ScoreInfo);
//listViewLog.Items.Add(Item);
}
}
}
Edit...
Here is the class im calling it from:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Handicap_Calculator
{
public partial class FormAddScore : Form
{
public DateTime date;
public string course;
public int holes;
public int score;
public float courseRating;
public float slopeRating;
public FormAddScore()
{
InitializeComponent();
}
private void FormAddScore_FormClosing(object sender, FormClosingEventArgs e)
{
FormMain.addScoreIsShown = false;
}
public void getscore()
{
try
{
date = dateTimePicker1.Value;
course = textBoxCourse.Text;
holes = Convert.ToInt16(textBoxHoles.Text);
score = Convert.ToInt16(textBoxScore.Text);
courseRating = Convert.ToSingle(textBoxCourseRating.Text);
slopeRating = Convert.ToSingle(textBoxSlopeRating.Text);
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void button1_Click(object sender, EventArgs e)
{
getscore();
FormMain.AddScore();
}
}
}
The simple solution is to define your methods AddScore and AddToList as non-static.
public void AddScore()
{
//your code
}
public void AddToList(string[] ScoreInfo)
{
// your code
}
If you want to use static methods you should pass the instance of your Form to the method, on which you want to add items to the ListView.
public static void AddScore(FormMain mainForm)
{
//your code
AddToList(mainForm, ScoreInfo);
}
public static void AddToList(FormMain mainForm, string[] ScoreInfo)
{
// your code
}
Update:
According to your updated code the solution is to pass the instance of your FormMain to your FormAddScore when you create it. In FormAddScore you store the reference to the FormMain instance to call the methods on.
public partial class FormAddScore : Form
{
// your code
private FormMain _mainForm;
public FormAddScore(){
InitializeComponent();
}
public FormAddScore(FormMain mainForm) : this(){
_mainForm = mainForm;
}
In your FormMain when you create the instance of FormAddScore you should use the constructor that expects an instance of FormMain
_FormAddScore = new FormAddScore(this);
With this setup you can change your methods to non-static and you can call the methods of FormMain in your FormAddScore, by using the stored reference in variable _mainForm.
_mainForm.AddScore();
Why this work:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
using IronRuby;
class Tutorial
{
static void Main(string[] args)
{
var engine = Ruby.CreateEngine();
engine.Runtime.Globals.SetVariable("Holly",new Holly("Test"));
engine.Execute("Holly.Say");
Console.ReadLine();
}
}
class Holly
{
string speech;
public Holly(string speech)
{
this.speech = speech;
}
public void Say()
{
Console.WriteLine("Hollu said " + this.speech);
}
}
and this is not work
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
using IronRuby;
class Tutorial
{
static void Main(string[] args)
{
var engine = Ruby.CreateEngine();
engine.Runtime.Globals.SetVariable("Mouse",new Holly("Test"));
engine.ExecuteFile("./test.rb");
Console.ReadLine();
}
}
class Holly
{
string speech;
public Holly(string speech)
{
this.speech = speech;
}
public void Say()
{
Console.WriteLine("Hollu said " + this.speech);
}
}
Try this
engine.ExecuteFile(#"..\test.rb");
Also wrap your code in try/catch statement and check for exception
try
{
var engine = Ruby.CreateEngine();
engine.Runtime.Globals.SetVariable("Holly",new Holly("Test"));
engine.ExecuteFile(#"..\test.rb");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
I am recently writing a wiimote program:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using WiimoteLib;
namespace WiiTester
{
public partial class Form1 : Form
{
Wiimote wm = new Wiimote();
public Form1()
{
InitializeComponent();
wm.WiimoteChanged += wm_WiimoteChanged;
wm.WiimoteExtensionChanged += wm_WiimoteExtensionChanged;
wm.Connect();
wm.SetReportType(InputReport.IRAccel, true);
}
void wm_WiimoteChanged(object sender, WiimoteChangedEventArgs args)
{
WiimoteState ws = args.WiimoteState;
if (ws.ButtonState.A == true)
{
wm.SetRumble(true);
}
else
{
wm.SetRumble(false);
}
}
void wm_WiimoteExtensionChanged(object sender, WiimoteExtensionChangedEventArgs args)
{
if (args.Inserted)
{
wm.SetReportType(InputReport.IRExtensionAccel, true);
}
else
{
wm.SetReportType(InputReport.IRAccel, true);
}
}
}
}
My wiimote keeps getting disconnected and this error keeps running on wm.Connect();
Timed out waiting for status report
Is there a solution?
I have a lot of experience with this library, and your problem is most likely being caused because you are calling SetRumble so often, this code:
void wm_WiimoteChanged(object sender, WiimoteChangedEventArgs args)
{
WiimoteState ws = args.WiimoteState;
if (ws.ButtonState.A == true)
{
wm.SetRumble(true);
}
else
{
wm.SetRumble(false);
}
}
Will call SetRumble constantly whether A is down or not, consider using this code instead:
bool rumbleOn = false;
void wm_WiimoteChanged(object sender, WiimoteChangedEventArgs args)
{
WiimoteState ws = args.WiimoteState;
bool newRumble = (ws.ButtonState.A == true);
if (rumbleOn != newRumble)
{
rumbleOn = newRumble;
wm.SetRumble(rumbleOn);
}
}
This way the set rumble method is only called when required and not constantly sending output reports to the WiiMote which causes the Bluetooth BUS to overload.