|
Thank you.
I created the following code.
Is this best way ?
using System;<br />
using System.Windows.Forms;<br />
using System.IO;<br />
<br />
class main {<br />
[STAThreadAttribute()]<br />
public static void Main() {<br />
<br />
LoginForm f = new LoginForm("Performing task x");<br />
<br />
for (int i = 0; i <= 100; i++) {<br />
f.Writeln("Login message " + i.ToString());<br />
}<br />
MessageBox.Show("");<br />
<br />
}<br />
<br />
class LoginForm : Form {<br />
<br />
ListBox lb;<br />
<br />
public LoginForm(string s) {<br />
Text = s;<br />
Left = 0;<br />
Top = 1000;<br />
Height = 500;<br />
Width = 2000;<br />
lb = new ListBox();<br />
lb.Dock = DockStyle.Fill;<br />
this.Controls.Add(lb);<br />
Show();<br />
}<br />
<br />
public void Writeln(string s) {<br />
<br />
lb.Items.Add(s);<br />
if (Control.ModifierKeys != Keys.Control) lb.TopIndex = lb.Items.Count - 1;<br />
}<br />
}<br />
}
Andrus
|
|
|
|
|
Does this work at all ?
Normally:
1. you create an instance of your main form inside the static Main method
2. you dont have Show() in a form's constructor
3. you pass the formk to Application.Run() which brings life to it (and does not return)
4. your main form organizes the remainder of the job; a good place to put some stuff is
in the Load event handler. Everything else typically is in handlers that react to
some event such as a button click, a timer tick, ...
That would also be what you get when you ask Visual Studio to create a new Windows
application. Yours looks like a Console application with a dead? form added to it.
|
|
|
|
|
> Does this work at all ?
I tried and it works OK.
> 1. you create an instance of your main form inside the static Main method
Yes, I create MDI parent form in my application.
Main() is for testing loginform() class only.
> 2. you dont have Show() in a form's constructor
Why not ?
I need to create and show login form using single command.
This works OK.
> dead? form added to it.
This form is not dead.
It shows login messages.
I it OK to use this Loginform call in MDI application ?
Andrus
|
|
|
|
|
AndrusM wrote: I it OK to use this Loginform call in MDI application ?
I dont know; I dont use MDI/SDI models. Sorry.
|
|
|
|
|
ListBox is only for WinForms application.
Every Winform application I have seen used SDI or MDI windows.
How can you create WinForm application without using SDI or MDI ?
Andrus
|
|
|
|
|
If SDI means you can see, read, operate on only one document or window, then I dont (unless
it happens to be a Console app).
If MDI is just the concept of working on more than one document at a time, then I am "using" MDI. If it involves special classes that support this, then I dont.
|
|
|
|
|
MDI means that there are parent window containing all other windows, having MDIPArent property set to true. Those other windows cannot moved outside of parent window.
Andrus
|
|
|
|
|
What type of application is your long running application service? Console App?
If it is a Console application then you can use the delegate event method mentioned, which when called posted the text passed as a param (keeping it simple)
If it is a service, is a windows form really the correct way to do it? manybe the Windiws Eventlog would be more appropriate.
If it is a windows application, look at Trace and Trace Listener (if I am thinking of the right things), the trace listener could access a windowow with a ListBox
Just ideas
|
|
|
|
|
I'm creating MDI Winforms application.
There is no trace listener which outputs text to winforms window visible for end user.
Also trace listeners work only when debugging application.
For this reason I need to create separate logging class.
Andrus
|
|
|
|
|
I understand that you are working in MDI, but what is your long running application? Is this the MDI app??
I assumed that the MDI app was a reporting tool
If it is long running are you sure this is appropriate as it screams service to me!
|
|
|
|
|
Luc,
thank you. Using your hint I created login form class below.
However I have the following issues with it:
1. Log message is shown only after messagebox is displayed.
How to force text to be displayed in login form immediately after calling Log method ?
2. Log window is displayed in top of screen.
Top = (int)(0.6 * (double)screen.WorkingArea.Height);
seems not working. How to show login form in lower part of screen ?
3. If there are more items than login area height, a scroll bar appears.
How to remove the scroll bar.
4. How to remove icon and all buttons from login form title bar ?
Andus.
using System;<br />
using System.Windows.Forms;<br />
using System.IO;<br />
<br />
class main {<br />
[STAThreadAttribute()]<br />
public static void Main() {<br />
<br />
Status s = new Status("Performing task x");<br />
s.Log("This text is not shown immediately");<br />
<br />
System.Threading.Thread.Sleep(8000);<br />
MessageBox.Show ("now it is shown");<br />
}<br />
<br />
public class Status : Form {<br />
<br />
ListBox lb;<br />
<br />
public Status(string title) {<br />
<br />
lb = new ListBox();<br />
lb.Dock = DockStyle.Fill;<br />
Controls.Add(lb);<br />
<br />
Screen screen = Screen.AllScreens[0];<br />
AutoScroll = false;<br />
FormBorderStyle = FormBorderStyle.FixedSingle;<br />
Text = title;<br />
Left = 0;<br />
Top = (int)(0.6 * (double)screen.WorkingArea.Height);<br />
Height = screen.WorkingArea.Height / 3;<br />
Width = screen.WorkingArea.Width;<br />
Show();<br />
}<br />
<br />
public void Log(string s) {<br />
lb.Items.Add(s);<br />
lb.TopIndex = lb.Items.Count - 1;<br />
}<br />
}<br />
}
Andrus
|
|
|
|
|
Hi,
1.
I am not surprised; you are doing it in a strange (probably wrong) way as I told you before.And it is only getting worse. You should not have the Sleep, dont do MessageBox if there is
something better (your form), dont include Show() in a form's constructor,
use Application.Run so you have a message pump, etc.
2.
A form's location is either automatic or user defined, depending on Form.StartPosition
3.
Normally the idea of logging is to have a record of the entire history.
If you dont like it, you could make the listbox taller, remove the oldest logs,
not use a listbox at all, etc
4.
read up on Form properties. If you set a sufficient number of them to false or "" you
can get rid of anything you dont want.
I must insist you study some more, and start doing things in a more conventional way;
otherwise you will have problems all over the place.
|
|
|
|
|
Luc,
1. This issue reproduction performs some task and exists.
It uses form only to show progress messages.
Since it does not need to enter to message bump it does not call Application.Run() method.
My actual MDI application calles Run() method for MDI parent form.
However, it encounters exactly the same issue.
So my questions were:
A. How to force listbox to show new item immediately, without entering wait state ?
B. How to force status window to continue display messages when I switch to other application and then back to my application ?
Current not responding appears and window stops updating.
2. StartPosition = FormStartPosition.Manual; fixes the issue. Thank you.
3. I close login window immediately after task is completed.
So I'm looking a way not to hold all messages in listbox and remove listbox scrollbar or to use some other method which does not waste memory.
4. After setting some properties to false, all icons from title bar disappear. Thank you.
Andrus
|
|
|
|
|
When I use ShowDialog directly from a form, it opens the second form and stops the first, but now I am trying do this by invoking it from a different thread with a timer in it and the call looks a bit like this now:
public partial class frmMain : Form
{
private delegate void ShowVoidDelegate();
private void ShowFrmList()
{
try
{
if (!FrmList.InvokeRequired)
{
FrmList.ShowDialog();
}
else
{
Invoke(new ShowVoidDelegate(ShowFrmList), null);
}
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
}
}
}
The problem now is, that frmMain doesn't wait anymore for the frmList form to close and executes all the code after the showdialog invoke inside frmMain.
How can I get the usual behavior back when using invoke, so that frmMain waits until frmList is closed ?
Thanks, Eike
|
|
|
|
|
Hi Eike,
if I understand you correctly, you have a main thread and a main form (obviously),
then have some job spun off into another thread, and all of a sudden that job needs
to interact with the user, hence wants to show a dialog, then has to continue with
its job.
I have three comments:
1.
The InvokeRequired/Invoke thing is all right; it operates in a synchronous mode, that is
Invoke will return only when the delegate it calls has finished. So that does not seem
to fit with your observation. I dont know what is wrong.
2.
There are several timer classes. I would recommend you look at the System.Windows.Forms.Timer
since that one fires on the main thread, so you probably would not need the Invoke stuff
at all.
3.
I am not fond of programs that throw modal dialogs at me without me asking them to do that.
If such app's functionality is anything less than exceptional, it will soon end up in
the trash bin.
Hope this helps.
|
|
|
|
|
Thanks, it is a compact framework project with several forms, and I want to control all the input and methods used in the different forms by an independent class, but maybe I just put all of it into the main form, if that is easier to manage after all.
With compact framework I can use only System.Windows.Forms.Timer or System.Threading.Timer (that's what I use right now). This controlling class gets all the input from the forms, and then checks what to do and sends out what the forms shall do back to them, or that was the plan at least.
Still, the problem remains, that the showdialog of the frmList does not make frmMain wait anymore with invoke, it just jumps right back into the code block that calls the ShowFrmList() function and continues while the frmList is still open.
The modal dialogs are useful where they are, for example things like user login at the start or after logout.
|
|
|
|
|
Hi Eike,
I have no experience with Compact Framework, I expect the subset it offers works the same
as on the classic Framework.
Manage all the forms from inside the main form (or possibly the static Main method)
seems the right approach.
If the timer's main job is GUI stuff, Forms.Timer is the right one.
If you were to use Forms.Timer and have its Tick handler create and ShowDialog() the
dialog, I am confident the main form would come to a halt until you close the dialog.
The behavior you describe is unfamiliar to me. Normally Application.Run() starts your
first message pump, the loop that keeps your GUI active. Calling ShowDialog() creates
a new message pump, that now gets all the messages, until the dialog gets closed.
You can interfere a bit by calling Application.DoEvents() but that is not recommended
in general (I use it only to restore a GUI after closing a dialog, when a short action
is to be executed on the main thread but you dont want to see the damaged GUI that long).
Did you by any chance try it also as a regular app on classic FrameWork ?
|
|
|
|
|
Hi Luc,
>Did you by any chance try it also as a regular app on classic FrameWork ?
No sorry, I didn't try that, the forms are all FormFactor PocketPC and I have some external compiled ARM .DLLs in it as well. I can't convert it to an ordinary Windows program that easy. But usually Compact and Full Framework behave the same way, just that a lot of nice methods and whole classes are missing in CF.
Nevertheless, if I actually change everything and use the timer in the main form, wouldn't it stop when other forms are opened as modal dialog ? I still need to control the other forms by some sort of timer, if the timer in the main form keeps running, that would work though.
Thanks, Eike
|
|
|
|
|
Hi Eike,
even with a modal dialog open, the main form stays alive: all its Window messages get handled
(e.g. it repaints when you move another window over it) and it keeps getting and executing
its timer ticks (watch the clock in apps that have it in the their status bar).
-- modified at 3:49 Tuesday 24th July, 2007
|
|
|
|
|
I am writing a Windows service in C#, in the constructor for the service I create and two threads to do the work, I then call Start() on both threads in the OnStart event. When I attempt to start the service in the Services manager I get the progress bar for about 30 seconds and then I get a dialog telling me the service did not respond in time (Error 1053).
I have added some debug comments and I can see that the OnStart event handler does return and that the two threads are running. From what I understand the service is up and running when the OnStart handler returns. What would be causing the timeout?
OS is Windows XP SP2, service is .NET 1.1
|
|
|
|
|
It is not completely clear to me from what you are describing, but I guess it is one of these
two:
- your service is not available soon enough, does your initial delay prevent it from
responding to the Services Maneger ? (i.e. did you do say a Thread.Sleep() in the main
thread, instead of using a timer ?)
- or your service exits for some reason (so it starts up OK, but you did not debug till the
end, or for some reason under Services Manager it fails (you are catching all exceptions
and logging them, are you ?)
Hope this helps
|
|
|
|
|
There are a few quirks about creating threads, one of these is that the response to Start (or is it initialise, been a while since I did this) cannot take more than 30 seconds and must return.
It is pretty normal (if not 100% correct or ideal) to start a seperate thread for the initialisation and then return imediatly to the Service Control Manager. This way you avoid the 30 second issue, especially when you need to do things like access a database etc
This way the Service Control Manager gets its desired service started / Initialised in time and leaves you to get on with the work you app needs to do in its own time.
|
|
|
|
|
plz just go through below code:
public class Base
{
public void GetbasePrivate() { }
protected void GetbaseProtected() { }
}
public class child : Base
{
protected void GetchildProtected() { }
public void GetchildPublic() { }
}
static class Program
{
static void Main()
{
Base objbase = new Base();
Base objbase = new Child(); //Please can any one explain these line in details.
}
}
Plz any one can tell me the differences of bold lines. Thx in advance.
Anmol Gupta
|
|
|
|
|
Hi,
new Base() creates an instance of Base, capable of whatever methods/properties are available
in the Base class.
Base objbase = new Base(); sets the variable objbase to refer to that instance, so now
you can do things such as objbase.GetbasePrivate() since that one is public (!)
new Child() creates an instance of Child, capable of whatever methods/properties are available
in the Child class or the Base class, since Child inherits from base.
if you were to do Child child=new Child(); you could now do both child.GetbasePrivate()
and child.GetchildPublic();
Base objbase = new Child(); creates an instance of Child, which automatically also is an
instance of Base since Child inherits from Base, and now the objbase variable refers to it
but acts as if it is a Base instance, forgetting all the extras that may come with
being a Child object too. So now you can do objbase.GetbasePrivate() but you cant
do objbase.GetchildPublic() since the Base class does not have such a method.
This is one of the fundamentals in object-orientation. It is not specific to C#.
If unclear, I strongly suggest you buy a book on C# (or on OO in general) and work
your way through it.
Good luck in the OO world !
|
|
|
|
|
Thanks for your quick response. I agree, what ever you have written there but Just I wanted to know that what is significant of Base objbase = new Child();.
I do not see any differences[Practically] between Base objbase = new Child(); and Base objbase = new Base();
If I am right then why do we use Base objbase = new Child();.
Thanks
Anmol gupta
|
|
|
|