Application crashes when trying to dispose an image - arrays

I'm creating an app with two pictureBoxes, where images load from a array and randomly change on every timer tick. I'm facing a problem of sometimes not loading the image, leaving the pictureBox with a little red cross. I read I should dispose the previous image before loading the new one (I'm a C# newbie), but I can't get it working without crashing the app on the first tick. Would you please help me out?
private void timer_Tick(object sender, EventArgs e)
{
index1 = rand.Next(0, pics.Length - 1);
index2 = rand.Next(0, pics.Length - 1);
pcb1.ImageLocation = pics[index1];
pcb2.ImageLocation = pics[index2];
}
try
{
pcb1.Image.Dispose();
pcb2.Image.Dispose();
index1 = rand.Next(0, pics.Length - 1);
index2 = rand.Next(0, pics.Length - 1);
pcb1.ImageLocation = pics[index1];
pcb2.ImageLocation = pics[index2];
}
catch (Exception)
{
throw;
}
- tells me System.ArgumentException

A possible solution:
try
{
private void timer_Tick(object sender, EventArgs e)
{
index1 = rand.Next(0, pics.Length);
if (File.Exists(pics[index1]))
{
Image img1 = Image.FromFile(pics[index1]);
pcb1.Image = img1;
}
index2 = rand.Next(0, pics.Length);
if (File.Exists(pics[index2]))
{
Image img2 = Image.FromFile(pics[index2]);
pcb2.Image = img2;
}
}
}
catch (OutOfMemoryException oomEx)
{
MessageBox.Show("Not a valid image.");
}
catch (Exception ex)
{
//all others...respond appropriately
}

Related

C# Why do I get duplicate records back when I return data from SQL to a dataset?

Im new to C#, so bear with me. Im using C#, a Form, and SQL Server 2012.
I have written some code that uses a Background Worker (from the form designer) and a progress bar to illustrate to the user the percentage of data that needs to be loaded from a SQL query until all records are completely read.
The problem Im having is that when the Worker is completed, I get many duplicate records listed in the datagridview. I should be getting only 14 returned records from my query, but I get many more (which are duplicates).
Im not sure why? Im sure there is a bug here (and that my beginnner code can be improved).
Can someone help my understand why Im getting duplicate records once the worker completes? My code is below
private void button2_Click(object sender, EventArgs e)
{
bgw.WorkerReportsProgress = true;
bgw.WorkerSupportsCancellation = false;
bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
bgw.ProgressChanged += new ProgressChangedEventHandler(bgw_ProgressChanged);
bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
System.Threading.Thread.Sleep(10);
bgw.RunWorkerAsync();
}
DataSet ds = new DataSet();
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
string query = "Select * from Stars_Pillars";
string connetionString = null;
SqlConnection cnn;
connetionString = "Server=xxx\\xxx;Initial Catalog=xxx;User ID=xxx;Password=xxx;";
cnn = new SqlConnection(connetionString);
SqlDataAdapter da = new SqlDataAdapter(query, cnn);
//DataSet ds = new DataSet();
try
{
cnn.Open();
int resda, startrow, pagesize, pageno;
pagesize = getRowCount();
progressBar1.Maximum = pagesize;
pageno = 1;
ds.Tables.Clear();
dataGridView1.Rows.Clear();
while (true)
{
if (!bgw.CancellationPending)
{
startrow = pageno;
resda = da.Fill(ds, startrow, pagesize, "Stars_Pillars");
if (resda == 0)
{
e.Cancel = true;
break;
}
else
{
System.Threading.Thread.Sleep(10);
int percents = (pageno * 100 / pagesize);
bgw.ReportProgress(percents, pageno);
pageno++;
}
}
else
{
e.Cancel = true;
break;
}
}
da.Dispose();
cnn.Close();
cnn.Dispose();
}
catch (Exception ex)
{
MessageBox.Show("Can not open connection ! ");
}
}
private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.PerformStep();
}
private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
progressBar1.Value = progressBar1.Maximum;
progressBar1.Visible = false;
dataGridView1.DataSource = ds.Tables[0];
}
private int getRowCount()
{
int count = 0;
string connetionString;
connetionString = "Server=xxxx\\xxxx;Initial Catalog=xxxx;User ID=xxxx;Password=xxxx;";
SqlConnection conn = new SqlConnection(connetionString);
string sql = "SELECT COUNT(Serial_Number) FROM [Stars_Pillars]";
SqlCommand cmd = new SqlCommand(sql, conn);
try
{
conn.Open();
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
count = (int)dr[0];
}
}
catch { }
finally
{
conn.Close();
}
return count;
}
there is a lot of improvements to make in your code...you should never use while (true) it is extremely bad practice and you can end with infinite loop. also, there is no way to measure and show progress of filling a dataset with dataAdapter.
if the operation takes time show a Marquee style progress bar.
for start try this code to load data from database to the DataSet object:
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
try
{
string query = "Select * from Stars_Pillars";
connetionString = "Server=xxx\\xxx;Initial Catalog=xxx;User ID=xxx;Password=xxx;";
using(cnn = new SqlConnection(connetionString))
{
cnn.Open();
using(SqlDataAdapter da = new SqlDataAdapter(query, cnn))
{
adapter.Fill(ds);
cnn.Close();
}
}
} catch (Exception ex) {
// handle errors here and close connetion if its open
}
}
You must be getting an exception with your code.
You cannot access UI element from bgwDoWork()
The below line must be failing.
dataGridView1.Rows.Clear();
Please check.

cannot find symbol ActionListener and try catch

I have a problem w my applet: shortly speaking, I want to "take" the variable curreny which is taken from xml and print it when I click on the button OK. The error I get is: error: cannot find symbol curreny. The problem is not importing variable from xml, because I checked separately if it works.
Sorry for the messy code, I'm new to java. All the neccessary packages are imported in the original source, but i didnt put it here just to make the code shorter. EDIT: I deleted part of the code consisting GUI to make it shorter, as you suggested.
public class App2 extends Applet implements ActionListener {
TextField T1 = new TextField();
Label L1 = new Label();
/* GUI code here */
public void actionPerformed(ActionEvent ae)
{
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document xmlDocument = db.parse(new URL("http://www.nbp.pl/kursy/xml/LastA.xml").openStream());
xmlDocument.getDocumentElement().normalize();
XPath xPath = XPathFactory.newInstance().newXPath();
String expression = "/tabela_kursow/pozycja[3]/kurs_sredni";
// System.out.println(expression);
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
// System.out.println(nodeList.item(i).getFirstChild().getNodeValue());
String kurs_dolara = nodeList.item(i).getFirstChild().getNodeValue();
double d_kurs_dolara = Double.parseDouble(kurs_dolara.replace(',', '.'));
System.out.println(d_kurs_dolara*6);
}
expression = "/tabela_kursow/pozycja[8]/kurs_sredni";
nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
String kurs_euro = nodeList.item(i).getFirstChild().getNodeValue();
double d_kurs_euro = Double.parseDouble(kurs_euro.replace(',', '.'));
System.out.println(d_kurs_euro*6);
}
expression = "/tabela_kursow/pozycja[11]/kurs_sredni";
nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
String kurs_funta = nodeList.item(i).getFirstChild().getNodeValue();
double d_kurs_funta = Double.parseDouble(kurs_funta.replace(',', '.'));
System.out.println(d_kurs_funta*6);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (XPathExpressionException e) {
e.printStackTrace();
}
String wynik = String.valueOf(d_kurs_euro);
L1.setText(wynik);
repaint();
}}

Click event for button in winform is firing repeatedly for number of values in List

I have a windows form (parent) that takes a value from textbox and then opens child form which then uses that value to select an image from a directory. When multiple images are found for the particular value, I have the form modified to display a couple of buttons to navigate (Next & Previous) to display the different images. Upon first opening the parent form, entering a value and then using form.show() to display the child form – everything works as expected. But if another value is entered into parent form (child form can still be open or exited (hidden)) and the ‘Next’ button is clicked the code in the click event is running over again for however many number of images are in the List(imagesFound). Say I have 3 images in the List(imagesFound) and I step through the code in debug mode the btnNext click event fires 3 times in a row. This of course runs GetMultiImages method which causes sequence of displaying the images to be all of. And again, this doesn’t happen the first time a value is entered into parent form. I’ve made sure the list and other variables are cleared out in GetImage method. I’m stumped…any ideas?
Form1:
public partial class Form1 : Form
{
private string parcelID;
Form2 viewer = new Form2();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
parcelID = txtParID.Text;
ShowViewer();
}
private void ShowViewer()
{
viewer.GetImage(parcelID);
if (viewer.NoImageFound == true)
{
viewer.Show();
viewer.Focus();
}
else if (viewer.NoImageFound == false)
{
viewer.Hide();
}
}
}
Child Form:
public partial class Form2 : Form
{
public Button btnNext = new Button();
public Button btnPrev = new Button();
private List<string> imagesFound = new List<string>();
private string Path;
private string parcel;
private int increment;
private int maxNum;
public bool NoImageFound;
//multi image members
private string firstMultiItem;
private string selectMultiImage;
Image parMultiImage;
public Form2()
{
InitializeComponent();
}
public void GetImage(string ParcelID)
{
NoImageFound = true;
parcel = ParcelID;
increment = 0;
maxNum = 0;
firstMultiItem = null;
selectMultiImage = null;
parMultiImage = null;
imagesFound.Clear();
Path = "........\\Images\\";
try
{
if (!string.IsNullOrEmpty(parcel))
{
string parcelTrim = parcel.Substring(0, 6);
Path = Path + parcelTrim + "\\";
foreach (string s in Directory.GetFiles(Path, parcel + "_" + "*"))
{
string trimString = s.Replace(Path, "");
imagesFound.Add(trimString);
}
if ((imagesFound.Count == 0))
{
MessageBox.Show("No images found for ParcelID: " + parcel);
picBox.Image = null;
this.Text = "";
NoImageFound = false;
}
else
{
if (imagesFound.Count == 1)
{
string firstItem = imagesFound[0].ToString();
string selectImage = Path + firstItem;
Image parImage = Image.FromFile(selectImage);
//in order to access the picture box control you have to change it's
//access modifier (Modifier) from private to public. Defaults to private
picBox.Image = parImage;
picBox.SizeMode = PictureBoxSizeMode.StretchImage;
this.Text = parcel;
SingleForm();
}
else if (imagesFound.Count > 1)
{
firstMultiItem = imagesFound[0].ToString();
maxNum = imagesFound.Count;
selectMultiImage = Path + firstMultiItem;
parMultiImage = Image.FromFile(selectMultiImage);
picBox.Image = parMultiImage;
picBox.SizeMode = PictureBoxSizeMode.StretchImage;
this.Text = parcel;
MultiImageForm();
}
}
}
else
{
MessageBox.Show("No ParcelID");
}
}
catch (DirectoryNotFoundException)
{
string text = parcel;
MessageBox.Show("ParcelID: " + text + " could not be found. The directory may be missing.", "There's a problem locating the image.",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void SingleForm()
{
this.Height = 400;
btnNext.Visible = false;
btnPrev.Visible = false;
}
private void MultiImageForm()
{
//set form properties
this.Text = parcel;
this.Height = 432;
//set btnNext properties
btnNext.Location = new Point(307, 375);
btnNext.Size = new Size(75, 25);
btnNext.Font = new Font("Maiandra GD", 10, FontStyle.Bold);
btnNext.Text = ">>";
//add btnNext to form
this.Controls.Add(btnNext);
btnNext.Visible = true;
btnNext.Enabled = true;
//creating event handler for btnNext
btnNext.Click += new EventHandler(btnNext_Click);
//set btnPrev properties
btnPrev.Location = new Point(12, 375);
btnPrev.Size = new Size(75, 25);
btnPrev.Font = new Font("Maiandra GD", 10, FontStyle.Bold);
btnPrev.Text = "<<";
//add btnPrev to form
this.Controls.Add(btnPrev);
btnPrev.Visible = true;
btnPrev.Enabled = false;
//creating event handler for btnPrev
btnPrev.Click += new EventHandler(btnPrev_Click);
}
private void GetMultiImages()
{
try
{
firstMultiItem = imagesFound[increment].ToString();
selectMultiImage = Path + firstMultiItem;
parMultiImage = Image.FromFile(selectMultiImage);
picBox.Image = parMultiImage;
picBox.SizeMode = PictureBoxSizeMode.StretchImage;
}
catch (IndexOutOfRangeException)
{
MessageBox.Show("Index was out of range.");
}
}
private void btnNext_Click(object sender, System.EventArgs e)
{
if (increment != maxNum - 1)
{
increment++;
GetMultiImages();
}
EnableButtons();
}
private void btnPrev_Click(object sender, System.EventArgs e)
{
if (increment > 0)
{
increment--;
GetMultiImages();
}
EnableButtons();
}
private void EnableButtons()
{
if (increment == 0)
{
btnPrev.Enabled = false;
btnNext.Enabled = true;
}
else if (increment > 0 & increment != maxNum - 1)
{
btnPrev.Enabled = true;
btnNext.Enabled = true;
}
else if (increment == maxNum - 1)
{
btnPrev.Enabled = true;
btnNext.Enabled = false;
}
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
//overriding closing event
this.Hide();
e.Cancel = true;
}
}
//creating event handler for btnNext
btnNext.Click += new EventHandler(btnNext_Click);
That's a bug. You keep adding a Click event handler for the button, each time you call MultiImageForm(). So the event handler runs multiple times for a single click.
Only add event handlers in the form constructor so you can be sure it is only done once.

WPF: Storyboard loop object owned by another thread

Hi all my simple code looks like this
private void flipForeverever(object sender, EventArgs args)
{
moveYs = new DoubleAnimation();
m2oveYs = new DoubleAnimation();
try
{
sf.Remove(this);
sf.Children.Clear();
}
catch (Exception e)
{
}
if (firstPanelAngle == 360)
{
moveYs.To = 180;
moveYs.From = 0;
}
else
{
moveYs.To = 360;
moveYs.From = 180;
}
if (secondPanelAngle == 360)
{
m2oveYs.To = 180;
m2oveYs.From = 0;
}
else
{
m2oveYs.To = 360;
m2oveYs.From = 180;
}
sf = (Storyboard)FindResource("Storyboard1");
Storyboard.SetTargetName(moveYs, "rotatePanel");
Storyboard.SetTargetProperty(moveYs, new thisPropertyPath(AxisAngleRotation3D.AngleProperty));
Storyboard.SetTargetName(m2oveYs, "rotateSecond");
Storyboard.SetTargetProperty(m2oveYs, new PropertyPath(AxisAngleRotation3D.AngleProperty));
sf.Children.Add(moveYs);
sf.Children.Add(m2oveYs);
// sf.RepeatBehavior = RepeatBehavior.Forever;
if (flipForever)
{
sf.Completed += new EventHandler(delaythespin);
sf.Begin(this);
}
}
private void delaythespin(object sender, EventArgs args)
{
sf.Stop(this);
System.Timers.Timer timer = new System.Timers.Timer(500);
timer.Elapsed += new System.Timers.ElapsedEventHandler(flipForeverever);
timer.Enabled = true;
firstPanelAngle = rotatePanel.Angle;
secondPanelAngle = rotateSecond.Angle;
timer.Start();
}
So basically i call flipForeverever through a click call and it is supposed to loop forever until i set flipforever to false... But then it is giving me this error...
The calling thread cannot access this object because a different thread owns it.
Any help will really be appreciated
It sounds like you might be having thread affinity problems. Have you tried using a DispatcherTimer instead of a System.Timers.Timer?
private DispatcherTimer _timer;
private void GoButton_Click(object sender, RoutedEventArgs e)
{
_timer = new DispatcherTimer(); // create timer
_timer.Interval = new TimeSpan(0, 0, 1); // tick every 1s
_timer.Tick += new EventHandler(_timer_Tick); // method to call
_timer.Start(); // start timer
}
void _timer_Tick(object sender, EventArgs e)
{
// we should be on the correct thread now
GoButton.Background = Brushes.Aqua;
}
Or, if you need to use System.Timers.Timer, use Invoke or BeginInvoke to get on the correct thread after the timer fires?
private System.Timers.Timer _timer;
private void GoButton_Click(object sender, RoutedEventArgs e)
{
_timer = new System.Timers.Timer(1000);
_timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed);
_timer.Start();
}
void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
// use Dispatcher.Invoke on the UI object that you want to modify
// to get on the correct thread for that UI object
GoButton.Dispatcher.Invoke((ThreadStart)(() =>
{
GoButton.Background = Brushes.Aqua;
}));
}

Thread and UI in WPF

This is XAML with a button and 3 progress bars
TestBtn
this is the thread to update the 3 progress bars..
Thread thread = new Thread(
new ThreadStart(
delegate()
{
progressBar1.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(
delegate()
{
int x=0;
while(true)
{
x++;
Thread.Sleep(50);
progressBar1.Value = x;
if (x>100)
{
break;
}
}
MessageBox.Show(" Complete ");
}
));
progressBar2.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(
delegate()
{
int y = 0;
while (true)
{
Thread.Sleep(50);
y = y + 2;
progressBar2.Value = y;
if (y > 100)
{
break;
}
}
MessageBox.Show(" Complete ");
}
));
progressBar3.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(
delegate()
{
int z = 0;
while (true)
{
Thread.Sleep(50);
z = z + 3;
progressBar3.Value = z;
if (z > 100)
{
break;
}
}
MessageBox.Show(" Complete ");
}
));
)
);//end of thread
thread.Start();
}
when i run this, all the 3 progress bars are updated to 100 percent at last(all are reaching directly to 100 at the same time) and it is not showing any increments from 0 to 100.
What i need is a thread with 3 item , where each will update the UI at the same time.So here at the same time all these 3 progress bars have to start and they have finish according to the loop..
(When we are copying files, in the UI , copying description is changing at the same time progress bar has to be updated.I want similar to that.So i think if i can understand a small example like this, then i can sort the required one)
You could always use a BackgroundWorker, example by Figo Fei (altered slightly):
private void button1_Click(object sender, EventArgs e)
{
progressBar1.Maximum = 100;
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// This would be the load process, where you put your Load methods into.
// You would report progress as something loads.
for (int i = 0; i < 100; i++)
{
Thread.Sleep(100);
backgroundWorker1.ReportProgress(i); //run in back thread
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) //call back method
{
progressBar1.Value = e.ProgressPercentage;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) //call back method
{
progressBar1.Value = progressBar1.Maximum;
}
One of the lovely thing about the BackgroundWorker is that it does run all the "heavy lifting" on a worker thread, but reports back to the UI thread. So by using the above code to your own needs, you should solve your problem.

Resources