|
try / catch can get expensive... but if you're happy with it
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
lol fair enough... ill have a proper look through the singleton stuff later and have a go...
|
|
|
|
|
It's dead easy really.
public sealed class SingletonForm : Form
{
SingletonForm() { }
public static SingletonForm Instance
{
get { return Nested.instance; }
}
private class Nested
{
static Nested() { }
internal static readonly SingletonForm instance = new SingletonForm();
}
} Now when ever you need the form, just use SingletonForm.Instance followed by whatever property/method etc you want. It will always be the same form but it won't be instanciated until you first reference it, and it's thread safe.
Based on the samples (the last one) here[^].
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
ok brill,
that was pretty easy to use, fine with Show() but i get an error with ShowDialog(): "Form that is already visible cannot be displayed as a modal dialog box. Set the form's visible property to false before calling showDialog." id like to use showdialog as it lets me handle setting changes better when the form closes.
heres what i did in my form:
public partial class Settings : Form<br />
{<br />
public Settings()<br />
{<br />
InitializeComponent();<br />
}<br />
public static Settings Instance<br />
{<br />
get { return Nested.instance; }<br />
}<br />
private class Nested<br />
{<br />
static Nested() { }<br />
internal static readonly Settings instance = new Settings();<br />
}<br />
}
|
|
|
|
|
This works perfectly for me
public sealed partial class Settings : Form
{
private Settings()
{
InitializeComponent();
}
public static Settings Instance
{
get { return Nested.instance; }
}
private class Nested
{
static Nested() { }
internal static readonly Settings instance = new Settings();
}
} No problems with ShowDialog or anything else at all.
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
weird it was only if i ran ShowDialog() twice that it did it BTW
heres the method:
public void COMMenuItem_Click(object sender, EventArgs e)
{
Settings.Instance.ShowDialog();
}
first time, it shows fine, but second time this is ran, i get the error.
this is supposed to work without a try...catch right?
|
|
|
|
|
Yeah, no need for try catch. I called Settings.Instance.ShowDialog(); twice in succession and it was no problem. ShowDialog returns with the form's visible state to false so it's not possible.
The only way that can happen is if the method that uses the ShowDialog is being called asynchronously from another thread, or if Show() has previously been used and the form wasn't closed, or the Settings form tries to show itself whilst already visible.
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
im not too sure whats going on with it then.
the showdialog() is ran whenever i click a button in a right click menu of an icon... i think the event is allowed to be called even when the form is already there, so perhaps the problem is here:
ToolStripMenuItem COMMenuItem = new ToolStripMenuItem("COM Port", null, new EventHandler(COMMenuItem_Click));
|
|
|
|
|
samskiter wrote: is allowed to be called even when the form is already there
Yeah, that's your problem.
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
so making a it a singleton wont work?
|
|
|
|
|
A singleton fulfils you original objective of only having one instance of the form and it not being instanciated right at the start of your application.
If you're trying to show the same instance again before the first one is closed then you've got some serious problems elsewhere in your code that need rethinking.
Using a try...catch to solve a bad coding issue is no real solution. Identify and fix the problem.
Are you trying to show the dialog again from itself? If not, how can anything else (menus or otherwise) be accessible? The dialog form will block until closed.
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
Where is this menu - is it a context menu on a NotifyIcon?
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
yes, its a notifyicon
it is defined in the Main() of my program:
public void OldMain()
{
if (SerPort.OpenPort())
{
icn = new NotifyIcon();
ContextMenuStrip menu = new ContextMenuStrip();
icn.ContextMenuStrip = menu;
ToolStripMenuItem COMMenuItem = new ToolStripMenuItem("COM Port", null, new EventHandler(this.COMMenuItem_Click));
ToolStripMenuItem ExitMenuItem = new ToolStripMenuItem("Exit", null, new EventHandler(ExitMenuItem_Click));
ToolStripSeparator separator = new ToolStripSeparator();
menu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { COMMenuItem, separator, ExitMenuItem });
icn.Visible = true;
icn.Icon = Properties.Resources.ehshell_IDI_APP1;
icn.ShowBalloonTip(3000, "Connected", "Duke Box is Connected", ToolTipIcon.Info);
MediaCenterController MCC = new MediaCenterController();
MCC.MediaStateChange += new MediaCenterController.MediaCenterHandler(SerPort.MediaCenter_Running);
MCC.MediaStateChange += new MediaCenterController.MediaCenterHandler(MediaCenter_Running);
Thread trd = new Thread(new ThreadStart(MCC.MediaCenterRunning));
trd.IsBackground = true;
trd.Start();
Application.Run();
}
else
{
}
}
i have checked the thread is not causing the problem, there is not way for the event to be fired from the thread...
|
|
|
|
|
samskiter wrote: yes, its a notifyicon
... now it makes sense!
No need to try/catch, just disable the menu item in the click handler before the ShowDialog and enable it again afterwards.
private void COMMenuItem_Click(object sender, EventArgs e)
{
COMMenuItem.Enabled = false;
Settings.ShowDialog();
COMMenuItem.Enabled = true;
}
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
BAGH! more of the same; despite declaring like this: public ToolStripMenuItem COMMenuItem;
im getting another "Object reference not set to an instance of an object." error when i click the button!
i quite like the behaviour of the properties window of the system clock (right click the clock and click properties twice)...
|
|
|
|
|
That line of code doesn't create an instance of a ToolStripMenuItem. It needs to be:
public ToolStripMenuItem COMMenuItem = new ToolStripMenuItem();
That's not done with ShowDialog. It's a normal Show() and it just checks to see if it's already visible. If not, it shows it. if it is, it justs focuses it.
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
DaveyM69 wrote: That line of code doesn't create an instance of a ToolStripMenuItem
sorry, i thought the instance created in my OldMain method would be public and so would work... i tried what you suggested with showdialog before and got another error, but with show its alright.
just a couple more things:
1. it doesnt give focus, is this something i should include int he singleton code
2. upon closing and reopening the form, i get an error "Cannot access a disposed object." i think this is part of the forms coding, to dispose itself when it is closed? when i was using try...catch, i had to include a couple of lines after showdialog:
setting.Dispose();
setting = null;
i believe this is the solution so im trying to do that with Settings.Instance, but its throwing up an error about being read only. so, after removing the = null; line it ran, but the form would close straight away, which has led me to realise that...
because i am using Show, disabling the button isn't working as the button is re-enabled straight away! so im still getting the same error if i try and open the form twice!
|
|
|
|
|
Yeah, using show the form will close and dispose when closed. You can catch the FormClosing event from the main program and cancel the close but hide instead.
void Instance_FormClosing(object sender, FormClosingEventArgs e)
{
if (!Disposing)
{
e.Cancel = true;
Settings.Instance.Hide();
}
}
private void COMMenuItem_Click(object sender, EventArgs e)
{
if (Settings.Instance.Visible)
Settings.Instance.Focus();
else
Settings.Instance.Show();
}
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
ok, but doesnt hiding it mean that once created the form will always exist?
|
|
|
|
|
OK, back to square one. I thought that's what you wanted.
If not, then just create an instance each time you need it testing IsDisposed and null and forget about show dialog, singletons and everything else!
Settings formSettings;
private void COMMenuItem_Click(object sender, EventArgs e)
{
if (formSettings == null || formSettings.IsDisposed)
formSettings = new Settings();
if (formSettings.Visible)
formSettings.Focus();
else
formSettings.Show();
}
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
haha! sorry for the trouble! getting confused talking to 3 people, what i have told who!
so that is a less heavy version of:
try
{
setting.Activate();
}
catch
{
setting = new Settings();
setting.ShowDialog();
setting.Dispose();
setting = null;
}
?
just tried it and it works perfectly, thanks for the help! out of interest, if this code is run after a form has previously been created and then closed, i assume the formSettings.IsDisposed case deals with it? but does the new formSettings replace the old one? or does it create new ones over and over and fill up memory?
while your here, do you know if it is possible to include a driver installation along with my project (drivers not made by me)? i do not have a .exe for the drivers, just the files which you have to point windows in the direction of when the device is first plugged in that are then installed by windows.
thanks again!
|
|
|
|
|
No memory overhead at all. The GC will clean up automatically for you.
Yeah, if there's no installer you can include the files in your setup project and copy them to
Environment.GetFolderPath(Environment.SpecialFolder.System)) and windows should be able to find them automatically.
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
your a star! im not at the stage of testing that yet, but thats great!
i followed this guide earlier: [^]
is this bad practise to create a loop to fire an event?
|
|
|
|
|
I haven't read the whole article, just a quick 'speed skim' but I wouldn't day it's bad practice as such. If an event needs to fire at a regular time, I'd do it asynchronously so the invoked method doesn't block the callee.
I have an article Events Made Simple[^] that may be worth a read if you want to learn about events.
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
interesting, your final solution looks similar to what i have in my code. but doesnt it rely on an event that is built into a textbox (textBox1_TextChanged)? what if (like i found) there is nothing to start the event? specifically, i wanted to check if a process has begun or ended. i created a method that can check for this, but surely, even if i run it asynchronously, it will only check once, then return? so at the heart of an event that is always checking, there must be a loop?
i heard the word "hook" thrown around... would a 'hook' allow me to utilise a system event for a specific process ending/starting?
i think i have done it asynchronously in my project, by creating a new thread for the method, a bit like BeginInvoke does...
|
|
|
|