| Home | Forums | Reviews | Articles | Register |
![]() |
| Thread Tools | Rate Thread |
|
|
|
| |
|
Ying-Shen Yu
Guest
Posts: n/a
|
hello, Lionel,
I wrote a test as you said, and it works properly without that exception. Could you give me some more information to reproduce the problem? The following is my test code. You may create a new Windows Application and replace the code with the following one. click the New Thread button ,you will see a new form with no border. In addition , It seems that your problem has some relation with the data updating mechanism. I hope you can look into it and give me more information about that exception. Thanks, using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.Threading; namespace multithread_UI_update { /// <summary> /// Summary description for Form1. /// </summary> public class Form1 : System.Windows.Forms.Form { private System.Windows.Forms.Button button1; private Thread thread = null; private Form2 form = null; /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.Container components = null; public Form1() { // // Required for Windows Form Designer support // InitializeComponent(); // // TODO: Add any constructor code after InitializeComponent call // } /// <summary> /// Clean up any resources being used. /// </summary> protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.button1 = new System.Windows.Forms.Button(); this.SuspendLayout(); // // button1 // this.button1.Location = new System.Drawing.Point(16, 8); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(144, 32); this.button1.TabIndex = 0; this.button1.Text = "New Thread"; this.button1.Click += new System.EventHandler(this.button1_Click); // // Form1 // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(184, 61); this.Controls.Add(this.button1); this.Name = "Form1"; this.Text = "Form1"; this.Closed += new System.EventHandler(this.Form1_Closed); this.ResumeLayout(false); } #endregion /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.Run(new Form1()); } private void button1_Click(object sender, System.EventArgs e) { thread = new Thread(new ThreadStart(ThreadProc)); thread.Start(); } private void ThreadProc() { try { form = new Form2(); form.Show(); Application.Run(form); } finally { form.Dispose(); } } private void Form1_Closed(object sender, System.EventArgs e) { if (thread.IsAlive) { form.Close(); } } } /// <summary> /// Summary description for Form2. /// </summary> public class Form2 : System.Windows.Forms.Form { private System.Windows.Forms.Label label1; /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.Container components = null; public Form2() { // // Required for Windows Form Designer support // InitializeComponent(); // // TODO: Add any constructor code after InitializeComponent call // } /// <summary> /// Clean up any resources being used. /// </summary> protected override void Dispose( bool disposing ) { if( disposing ) { if(components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.label1 = new System.Windows.Forms.Label(); this.SuspendLayout(); // // label1 // this.label1.Dock = System.Windows.Forms.DockStyle.Fill; this.label1.Location = new System.Drawing.Point(0, 0); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(292, 273); this.label1.TabIndex = 0; this.label1.Text = "label1"; // // Form2 // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(292, 273); this.Controls.Add(this.label1); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.Name = "Form2"; this.Text = "Form2"; this.ResumeLayout(false); } #endregion } } regards, Best regards, Ying-Shen Yu[MSFT] Microsoft Support Engineer This posting is provided "AS IS" with no warranties, and confers no rights. You assume all risk for your use. 2001 Microsoft Corporation. All rights reserved. |
|
||
|
||||
|
Lionel Johnson
Guest
Posts: n/a
|
Ying-Shen: Thanks for your prompt reply! Your code does indeed work and is very close to what I had. Unfortunately, I had code in the Resize event for the second form that assumed the presence of a Graphics object that I create in the Load event. It appears that when the form is created without a border, a Resize event occurs without the Load event occuring and hence the Graphics object is not created in time. In the case of a form with a border, the load event is executed first and no resize event occurs until after that point, by which time my Graphics object is available and all is OK. Now my only problem is that the individual forms (16 of them in my application) show up in the Alt-Tab list although I can successfully stop them appearing in the task bar (setting the ShowInTaskbar property to false). Please note that the reason that I am doing this is to avoid having to marshal the realtime updates in these "sub- forms" through the main UI thread since user interaction could (and does) interfere with the realtime drawing. I had another thought - although high level operations on controls must be marshalled through the thread on which the controls have been created, is it permissible to use control.CreateGraphics()(say on a Panel control) and then use the returned Graphics object in a separate thread? Of course this would need to be coupled with an override of the OnPaint method of the control with no contents including no call to the base.OnPaint() to avoid unexpected redrawing of the control. This appears to work, but I wonder if it is legal. This approach would achieve the same as with the separate forms previously discussed without the disadvantage of having them appear in Alt-tab list. Once again, thanks for your help Lionel >-----Original Message----- >hello, Lionel, > I wrote a test as you said, and it works properly without that >exception. Could you give me some more information to reproduce the problem? > The following is my test code. You may create a new Windows >Application and replace the code with the following one. >click the New Thread button ,you will see a new form with no border. >In addition , It seems that your problem has some relation with the data >updating mechanism. I hope you can look into it >and give me more information about that exception. >Thanks, > >using System; >using System.Drawing; >using System.Collections; >using System.ComponentModel; >using System.Windows.Forms; >using System.Data; >using System.Threading; > >namespace multithread_UI_update >{ > /// <summary> > /// Summary description for Form1. > /// </summary> > public class Form1 : System.Windows.Forms.Form > { > private System.Windows.Forms.Button button1; > private Thread thread = null; > private Form2 form = null; > /// <summary> > /// Required designer variable. > /// </summary> > private System.ComponentModel.Container components = null; > > public Form1() > { > // > // Required for Windows Form Designer support > // > InitializeComponent(); > > // > // TODO: Add any constructor code after InitializeComponent call > // > } > > /// <summary> > /// Clean up any resources being used. > /// </summary> > protected override void Dispose( bool disposing ) > { > if( disposing ) > { > if (components != null) > { > components.Dispose (); > } > } > base.Dispose( disposing ); > } > > #region Windows Form Designer generated code > /// <summary> > /// Required method for Designer support - do not modify > /// the contents of this method with the code editor. > /// </summary> > private void InitializeComponent() > { > this.button1 = new System.Windows.Forms.Button(); > this.SuspendLayout(); > // > // button1 > // > this.button1.Location = new System.Drawing.Point(16, 8); > this.button1.Name = "button1"; > this.button1.Size = new System.Drawing.Size(144, 32); > this.button1.TabIndex = 0; > this.button1.Text = "New Thread"; > this.button1.Click += new System.EventHandler(this.button1_Click); > // > // Form1 > // > this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); > this.ClientSize = new System.Drawing.Size(184, 61); > this.Controls.Add(this.button1); > this.Name = "Form1"; > this.Text = "Form1"; > this.Closed += new System.EventHandler(this.Form1_Closed); > this.ResumeLayout(false); > > } > #endregion > > /// <summary> > /// The main entry point for the application. > /// </summary> > [STAThread] > static void Main() > { > Application.Run(new Form1()); > } > > private void button1_Click(object sender, System.EventArgs e) > { > thread = new Thread(new ThreadStart (ThreadProc)); > thread.Start(); > } > > private void ThreadProc() > { > try > { > form = new Form2(); > form.Show(); > Application.Run(form); > } > finally > { > form.Dispose(); > } > } > > private void Form1_Closed(object sender, System.EventArgs e) > { > if (thread.IsAlive) > { > form.Close(); > } > } > } > /// <summary> > /// Summary description for Form2. > /// </summary> > public class Form2 : System.Windows.Forms.Form > { > private System.Windows.Forms.Label label1; > /// <summary> > /// Required designer variable. > /// </summary> > private System.ComponentModel.Container components = null; > > public Form2() > { > // > // Required for Windows Form Designer support > // > InitializeComponent(); > > // > // TODO: Add any constructor code after InitializeComponent call > // > } > > /// <summary> > /// Clean up any resources being used. > /// </summary> > protected override void Dispose( bool disposing ) > { > if( disposing ) > { > if(components != null) > { > components.Dispose (); > } > } > base.Dispose( disposing ); > } > #region Windows Form Designer generated code > /// <summary> > /// Required method for Designer support - do not modify > /// the contents of this method with the code editor. > /// </summary> > private void InitializeComponent() > { > this.label1 = new System.Windows.Forms.Label(); > this.SuspendLayout(); > // > // label1 > // > this.label1.Dock = System.Windows.Forms.DockStyle.Fill; > this.label1.Location = new System.Drawing.Point(0, 0); > this.label1.Name = "label1"; > this.label1.Size = new System.Drawing.Size(292, 273); > this.label1.TabIndex = 0; > this.label1.Text = "label1"; > // > // Form2 > // > this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); > this.ClientSize = new System.Drawing.Size(292, 273); > this.Controls.Add(this.label1); > this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; > this.Name = "Form2"; > this.Text = "Form2"; > this.ResumeLayout(false); > > } > #endregion > } >} > > >regards, > >Best regards, > >Ying-Shen Yu[MSFT] >Microsoft Support Engineer > >This posting is provided "AS IS" with no warranties, and confers no rights. >You assume all risk for your use. 2001 Microsoft Corporation. All rights >reserved. > >. > |
|
||
|
||||
|
Joe White
Guest
Posts: n/a
|
> is it permissible to use
> control.CreateGraphics()(say on a Panel control) and then > use the returned Graphics object in a separate thread? Absolutely. You can even call CreateGraphics() from the secondary thread -- the docs point out that CreateGraphics() is one of only four Control methods that can safely be called from other threads. I'm doing this in my RPG development kit (still in its infancy, but the painting-from-a-thread code is well established and working well). However, you do need to be careful: the control you're painting to needs to have a valid window handle, from the time you call CreateGraphics() until the time you dispose the Graphics object. Otherwise you'll get sporadic exceptions. From my early experience, it also seems that the control needs to be visible. My code takes the cautious approach, and doesn't start the thread-based painting until the control receives its first Paint event, and stops again when the form is minimized. This may not be necessary, but I don't get exceptions, so I'm happy. I also have code in the Closing event that waits for any in-progress paint events to finish, before allowing the form to close. The devil's in the details, and it took me a while to hit on the right approach, but my current code has been running successfully for a couple of weeks with no exceptions on shutdown. So it can be done. If you'd like to see my code, let me know, and I can e-mail it to you. |
|
||
|
||||
|
Ying-Shen Yu
Guest
Posts: n/a
|
Hello Lionel,
I think it's feasible to do drawing in a serperate UI worker thread, but I suggest you creating the graphics object in new thread, because the handle of the control(say panel) will not be changed after it created, and the CreateGraphics is thread-safe according to the MSDN, then different threads,can draw seperately with their own Graphics object. However, you should be very careful if your worker thread uses any members of the control,such as handling the resize event,closing event etc. On your previous thought, I think it's possible to get rid of the border by modifying the window style to toolwindow style (which will not show in the taskbar or alt-tab list),and then process the WM_NCCALCSIZE and WM_NCPAINT message of the form by yourself. In theory, there should be an style set to make the toolwindow withou a border, but I haven't found it, I will go on researching it and give you a example in the beginning of next week, if I find it. Thanks! Kind regards, Ying-Shen Yu [MSFT] Microsoft Support Engineer This posting is provided "AS IS" with no warranties, and confers no rights. You assume all risk for your use. 2001 Microsoft Corporation. All rights reserved. From: "Lionel Johnson" <(E-Mail Removed)> Subject: RE: Borderless controls in a separate thread Date: Thu, 7 Aug 2003 14:01:11 -0700 Newsgroups: microsoft.public.dotnet.framework.windowsforms Ying-Shen: Thanks for your prompt reply! Your code does indeed work and is very close to what I had. Unfortunately, I had code in the Resize event for the second form that assumed the presence of a Graphics object that I create in the Load event. It appears that when the form is created without a border, a Resize event occurs without the Load event occuring and hence the Graphics object is not created in time. In the case of a form with a border, the load event is executed first and no resize event occurs until after that point, by which time my Graphics object is available and all is OK. Now my only problem is that the individual forms (16 of them in my application) show up in the Alt-Tab list although I can successfully stop them appearing in the task bar (setting the ShowInTaskbar property to false). Please note that the reason that I am doing this is to avoid having to marshal the realtime updates in these "sub- forms" through the main UI thread since user interaction could (and does) interfere with the realtime drawing. I had another thought - although high level operations on controls must be marshalled through the thread on which the controls have been created, is it permissible to use control.CreateGraphics()(say on a Panel control) and then use the returned Graphics object in a separate thread? Of course this would need to be coupled with an override of the OnPaint method of the control with no contents including no call to the base.OnPaint() to avoid unexpected redrawing of the control. This appears to work, but I wonder if it is legal. This approach would achieve the same as with the separate forms previously discussed without the disadvantage of having them appear in Alt-tab list. Once again, thanks for your help Lionel >-----Original Message----- >hello, Lionel, > I wrote a test as you said, and it works properly without that >exception. Could you give me some more information to reproduce the problem? > The following is my test code. You may create a new Windows >Application and replace the code with the following one. >click the New Thread button ,you will see a new form with no border. >In addition , It seems that your problem has some relation with the data >updating mechanism. I hope you can look into it >and give me more information about that exception. >Thanks, > >using System; >using System.Drawing; >using System.Collections; >using System.ComponentModel; >using System.Windows.Forms; >using System.Data; >using System.Threading; > >namespace multithread_UI_update >{ > /// <summary> > /// Summary description for Form1. > /// </summary> > public class Form1 : System.Windows.Forms.Form > { > private System.Windows.Forms.Button button1; > private Thread thread = null; > private Form2 form = null; > /// <summary> > /// Required designer variable. > /// </summary> > private System.ComponentModel.Container components = null; > > public Form1() > { > // > // Required for Windows Form Designer support > // > InitializeComponent(); > > // > // TODO: Add any constructor code after InitializeComponent call > // > } > > /// <summary> > /// Clean up any resources being used. > /// </summary> > protected override void Dispose( bool disposing ) > { > if( disposing ) > { > if (components != null) > { > components.Dispose (); > } > } > base.Dispose( disposing ); > } > > #region Windows Form Designer generated code > /// <summary> > /// Required method for Designer support - do not modify > /// the contents of this method with the code editor. > /// </summary> > private void InitializeComponent() > { > this.button1 = new System.Windows.Forms.Button(); > this.SuspendLayout(); > // > // button1 > // > this.button1.Location = new System.Drawing.Point(16, 8); > this.button1.Name = "button1"; > this.button1.Size = new System.Drawing.Size(144, 32); > this.button1.TabIndex = 0; > this.button1.Text = "New Thread"; > this.button1.Click += new System.EventHandler(this.button1_Click); > // > // Form1 > // > this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); > this.ClientSize = new System.Drawing.Size(184, 61); > this.Controls.Add(this.button1); > this.Name = "Form1"; > this.Text = "Form1"; > this.Closed += new System.EventHandler(this.Form1_Closed); > this.ResumeLayout(false); > > } > #endregion > > /// <summary> > /// The main entry point for the application. > /// </summary> > [STAThread] > static void Main() > { > Application.Run(new Form1()); > } > > private void button1_Click(object sender, System.EventArgs e) > { > thread = new Thread(new ThreadStart (ThreadProc)); > thread.Start(); > } > > private void ThreadProc() > { > try > { > form = new Form2(); > form.Show(); > Application.Run(form); > } > finally > { > form.Dispose(); > } > } > > private void Form1_Closed(object sender, System.EventArgs e) > { > if (thread.IsAlive) > { > form.Close(); > } > } > } > /// <summary> > /// Summary description for Form2. > /// </summary> > public class Form2 : System.Windows.Forms.Form > { > private System.Windows.Forms.Label label1; > /// <summary> > /// Required designer variable. > /// </summary> > private System.ComponentModel.Container components = null; > > public Form2() > { > // > // Required for Windows Form Designer support > // > InitializeComponent(); > > // > // TODO: Add any constructor code after InitializeComponent call > // > } > > /// <summary> > /// Clean up any resources being used. > /// </summary> > protected override void Dispose( bool disposing ) > { > if( disposing ) > { > if(components != null) > { > components.Dispose (); > } > } > base.Dispose( disposing ); > } > #region Windows Form Designer generated code > /// <summary> > /// Required method for Designer support - do not modify > /// the contents of this method with the code editor. > /// </summary> > private void InitializeComponent() > { > this.label1 = new System.Windows.Forms.Label(); > this.SuspendLayout(); > // > // label1 > // > this.label1.Dock = System.Windows.Forms.DockStyle.Fill; > this.label1.Location = new System.Drawing.Point(0, 0); > this.label1.Name = "label1"; > this.label1.Size = new System.Drawing.Size(292, 273); > this.label1.TabIndex = 0; > this.label1.Text = "label1"; > // > // Form2 > // > this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); > this.ClientSize = new System.Drawing.Size(292, 273); > this.Controls.Add(this.label1); > this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; > this.Name = "Form2"; > this.Text = "Form2"; > this.ResumeLayout(false); > > } > #endregion > } >} > > >regards, > >Best regards, > >Ying-Shen Yu[MSFT] >Microsoft Support Engineer > >This posting is provided "AS IS" with no warranties, and confers no rights. >You assume all risk for your use. 2001 Microsoft Corporation. All rights >reserved. > >. > |
|
||
|
||||
|
Lionel Johnson
Guest
Posts: n/a
|
Joe:
Thanks for the reply and all of the additional useful information - its probably saved me an awful lot of time. If it is not too much trouble, I'll take up your offer to peek at the pertinent parts of your code - it will help to cement some of the ideas. Thanks very much Lionel >-----Original Message----- >> is it permissible to use >> control.CreateGraphics()(say on a Panel control) and then >> use the returned Graphics object in a separate thread? > >Absolutely. You can even call CreateGraphics() from the secondary >thread -- the docs point out that CreateGraphics() is one of only four >Control methods that can safely be called from other threads. I'm doing >this in my RPG development kit (still in its infancy, but the >painting-from-a-thread code is well established and working well). > >However, you do need to be careful: the control you're painting to >needs to have a valid window handle, from the time you call >CreateGraphics() until the time you dispose the Graphics object. >Otherwise you'll get sporadic exceptions. From my early experience, it >also seems that the control needs to be visible. My code takes the >cautious approach, and doesn't start the thread-based painting until the >control receives its first Paint event, and stops again when the form is >minimized. This may not be necessary, but I don't get exceptions, so >I'm happy. I also have code in the Closing event that waits for any >in-progress paint events to finish, before allowing the form to close. >The devil's in the details, and it took me a while to hit on the right >approach, but my current code has been running successfully for a couple >of weeks with no exceptions on shutdown. So it can be done. > >If you'd like to see my code, let me know, and I can e- mail it to you. > >. > |
|
||
|
||||
|
Lionel Johnson
Guest
Posts: n/a
|
Ying-Shen: Thanks for the additional information. I looked further at your suggestion for using a toolwindow style. Overrode WndProc() and did an immediate return without calling the base.WndProc() for WM_NCCALCSIZE and WM_NCPAINT and the border disappeared while the form stayed out of the Alt-Tab and taskbar list. Thanks Lionel >-----Original Message----- >Hello Lionel, > I think it's feasible to do drawing in a serperate UI worker thread, >but I suggest you creating the graphics object in new thread, because the >handle of the control(say panel) will not be changed after it created, and >the CreateGraphics is thread-safe according to the MSDN, then different >threads,can draw seperately with their own Graphics object. However, you >should be very careful if your worker thread uses any members of the >control,such as handling the resize event,closing event etc. > On your previous thought, I think it's possible to get rid of the border >by modifying the window style to toolwindow style (which will not show in >the taskbar or alt-tab list),and then process the WM_NCCALCSIZE and >WM_NCPAINT message of the form by yourself. In theory, there should be an >style set to make the toolwindow withou a border, but I haven't found it, I > will go on researching it and give you a example in the beginning of next >week, if I find it. > >Thanks! > > >Kind regards, > >Ying-Shen Yu [MSFT] >Microsoft Support Engineer > >This posting is provided "AS IS" with no warranties, and confers no rights. >You assume all risk for your use. 2001 Microsoft Corporation. All rights >reserved. > > > > > >From: "Lionel Johnson" <(E-Mail Removed)> >Subject: RE: Borderless controls in a separate thread >Date: Thu, 7 Aug 2003 14:01:11 -0700 >Newsgroups: microsoft.public.dotnet.framework.windowsforms > > > >Ying-Shen: > >Thanks for your prompt reply! Your code does indeed work >and is very close to what I had. Unfortunately, I had code >in the Resize event for the second form that assumed the >presence of a Graphics object that I create in the Load >event. It appears that when the form is created without a >border, a Resize event occurs without the Load event >occuring and hence the Graphics object is not created in >time. In the case of a form with a border, the load event >is executed first and no resize event occurs until after >that point, by which time my Graphics object is available >and all is OK. > >Now my only problem is that the individual forms (16 of >them in my application) show up in the Alt-Tab list >although I can successfully stop them appearing in the >task bar (setting the ShowInTaskbar property to false). > >Please note that the reason that I am doing this is to >avoid having to marshal the realtime updates in these "sub- >forms" through the main UI thread since user interaction >could (and does) interfere with the realtime drawing. > >I had another thought - although high level operations on >controls must be marshalled through the thread on which >the controls have been created, is it permissible to use >control.CreateGraphics()(say on a Panel control) and then >use the returned Graphics object in a separate thread? Of >course this would need to be coupled with an override of >the OnPaint method of the control with no contents >including no call to the base.OnPaint() to avoid >unexpected redrawing of the control. This appears to work, >but I wonder if it is legal. This approach would achieve >the same as with the separate forms previously discussed >without the disadvantage of having them appear in Alt-tab >list. > >Once again, thanks for your help > >Lionel > > >>-----Original Message----- >>hello, Lionel, >> I wrote a test as you said, and it works properly >without that >>exception. Could you give me some more information to >reproduce the problem? >> The following is my test code. You may create a new >Windows >>Application and replace the code with the following one. >>click the New Thread button ,you will see a new form with >no border. >>In addition , It seems that your problem has some >relation with the data >>updating mechanism. I hope you can look into it >>and give me more information about that exception. >>Thanks, >> >>using System; >>using System.Drawing; >>using System.Collections; >>using System.ComponentModel; >>using System.Windows.Forms; >>using System.Data; >>using System.Threading; >> >>namespace multithread_UI_update >>{ >> /// <summary> >> /// Summary description for Form1. >> /// </summary> >> public class Form1 : System.Windows.Forms.Form >> { >> private System.Windows.Forms.Button >button1; >> private Thread thread = null; >> private Form2 form = null; >> /// <summary> >> /// Required designer variable. >> /// </summary> >> private System.ComponentModel.Container >components = null; >> >> public Form1() >> { >> // >> // Required for Windows Form >Designer support >> // >> InitializeComponent(); >> >> // >> // TODO: Add any constructor code >after InitializeComponent call >> // >> } >> >> /// <summary> >> /// Clean up any resources being used. >> /// </summary> >> protected override void Dispose( bool >disposing ) >> { >> if( disposing ) >> { >> if (components != null) >> { >> components.Dispose >(); >> } >> } >> base.Dispose( disposing ); >> } >> >> #region Windows Form Designer generated >code >> /// <summary> >> /// Required method for Designer support - >do not modify >> /// the contents of this method with the >code editor. >> /// </summary> >> private void InitializeComponent() >> { >> this.button1 = new >System.Windows.Forms.Button(); >> this.SuspendLayout(); >> // >> // button1 >> // >> this.button1.Location = new >System.Drawing.Point(16, 8); >> this.button1.Name = "button1"; >> this.button1.Size = new >System.Drawing.Size(144, 32); >> this.button1.TabIndex = 0; >> this.button1.Text = "New Thread"; >> this.button1.Click += new >System.EventHandler(this.button1_Click); >> // >> // Form1 >> // >> this.AutoScaleBaseSize = new >System.Drawing.Size(5, 13); >> this.ClientSize = new >System.Drawing.Size(184, 61); >> this.Controls.Add(this.button1); >> this.Name = "Form1"; >> this.Text = "Form1"; >> this.Closed += new >System.EventHandler(this.Form1_Closed); >> this.ResumeLayout(false); >> >> } >> #endregion >> >> /// <summary> >> /// The main entry point for the >application. >> /// </summary> >> [STAThread] >> static void Main() >> { >> Application.Run(new Form1()); >> } >> >> private void button1_Click(object sender, >System.EventArgs e) >> { >> thread = new Thread(new ThreadStart >(ThreadProc)); >> thread.Start(); >> } >> >> private void ThreadProc() >> { >> try >> { >> form = new Form2(); >> form.Show(); >> Application.Run(form); >> } >> finally >> { >> form.Dispose(); >> } >> } >> >> private void Form1_Closed(object sender, >System.EventArgs e) >> { >> if (thread.IsAlive) >> { >> form.Close(); >> } >> } >> } >> /// <summary> >> /// Summary description for Form2. >> /// </summary> >> public class Form2 : System.Windows.Forms.Form >> { >> private System.Windows.Forms.Label label1; >> /// <summary> >> /// Required designer variable. >> /// </summary> >> private System.ComponentModel.Container >components = null; >> >> public Form2() >> { >> // >> // Required for Windows Form >Designer support >> // >> InitializeComponent(); >> >> // >> // TODO: Add any constructor code >after InitializeComponent call >> // >> } >> >> /// <summary> >> /// Clean up any resources being used. >> /// </summary> >> protected override void Dispose( bool >disposing ) >> { >> if( disposing ) >> { >> if(components != null) >> { >> components.Dispose >(); >> } >> } >> base.Dispose( disposing ); >> } >> #region Windows Form Designer generated >code >> /// <summary> >> /// Required method for Designer support - >do not modify >> /// the contents of this method with the >code editor. >> /// </summary> >> private void InitializeComponent() >> { >> this.label1 = new >System.Windows.Forms.Label(); >> this.SuspendLayout(); >> // >> // label1 >> // >> this.label1.Dock = >System.Windows.Forms.DockStyle.Fill; >> this.label1.Location = new >System.Drawing.Point(0, 0); >> this.label1.Name = "label1"; >> this.label1.Size = new >System.Drawing.Size(292, 273); >> this.label1.TabIndex = 0; >> this.label1.Text = "label1"; >> // >> // Form2 >> // >> this.AutoScaleBaseSize = new >System.Drawing.Size(5, 13); >> this.ClientSize = new >System.Drawing.Size(292, 273); >> this.Controls.Add(this.label1); >> this.FormBorderStyle = >System.Windows.Forms.FormBorderStyle.None; >> this.Name = "Form2"; >> this.Text = "Form2"; >> this.ResumeLayout(false); >> >> } >> #endregion >> } >>} >> >> >>regards, >> >>Best regards, >> >>Ying-Shen Yu[MSFT] >>Microsoft Support Engineer >> >>This posting is provided "AS IS" with no warranties, and >confers no rights. >>You assume all risk for your use. 2001 Microsoft >Corporation. All rights >>reserved. >> >>. >> > >. > |
|
||
|
||||
|
Joe White
Guest
Posts: n/a
|
I'm posting this in the NG in case the code would help anyone else out...
I just posted my multithreaded-painting code on my Web site. Go to http://www.excastle.com/Tyler/ and scroll to the bottom of the page, and click "Download Tyler technology preview demo #1". The parts that will probably interest you most are the SessionWindow and the SessionViewer. The SessionWindow mostly just passes some notifications (minimizing, closing) to the SessionViewer. The SessionViewer (which is a Control parented to the SessionWindow) does all the work of running a timer, locking critical sections as needed, etc. It has a property which I somewhat whimsically named "Happy", which determines whether painting can safely occur at this point in time: if the viewer is happy, it's safe for threads to paint. Happy starts off false, gets set to true when the SessionViewer gets its first paint message, then gets set back to false when the SessionWindow is minimized or closed. The Happy setter has a lock, which makes sure the flag won't actually get changed until any paint-operation-in-progress runs to completion. In turn, this ensures that the form can't be closed while painting is in progress. All my rendering is double-buffered. The locking mechanisms reflect this -- there are more stringent critical-section checks around the copy-to-screen operation, since that's where the cross-thread CreateGraphics() actually happens. If you have any questions about the code (I'm sure I could have documented some of it better, especially as regards *why* I did things a certain way), let me know -- either post here, or e-mail me. Hope this helps! Lionel Johnson wrote: > Joe: > > Thanks for the reply and all of the additional useful > information - its probably saved me an awful lot of time. > If it is not too much trouble, I'll take up your offer to > peek at the pertinent parts of your code - it will help to > cement some of the ideas. > > Thanks very much > > Lionel > > >>-----Original Message----- >> >>> is it permissible to use >>> control.CreateGraphics()(say on a Panel control) and >>> then use the returned Graphics object in a separate thread? >> >> Absolutely. You can even call CreateGraphics() from the >> secondary thread -- the docs point out that CreateGraphics() >> is one of only four Control methods that can safely be >> called from other threads. I'm doing this in my RPG >> development kit (still in its infancy, but the >> painting-from-a-thread code is well established and >> working well). >> >> However, you do need to be careful: the control you're >> painting to needs to have a valid window handle, from >> the time you call CreateGraphics() until the time you >> dispose the Graphics object. Otherwise you'll get >> sporadic exceptions. From my early experience, it >> also seems that the control needs to be visible. My >> code takes the cautious approach, and doesn't start the >> thread-based painting until the control receives its >> first Paint event, and stops again when the form is >> minimized. This may not be necessary, but I don't get >> exceptions, so I'm happy. I also have code in the >> Closing event that waits for any in-progress paint >> events to finish, before allowing the form to close. >> >> The devil's in the details, and it took me a while to >> hit on the right approach, but my current code has been >> running successfully for a couple of weeks with no >> exceptions on shutdown. So it can be done. >> >> If you'd like to see my code, let me know, and I can e- >> mail it to you. |
|
||
|
||||
|
Lionel Johnson
Guest
Posts: n/a
|
Joe:
Thanks - much appreciated Lionel >-----Original Message----- >I'm posting this in the NG in case the code would help anyone else out... > >I just posted my multithreaded-painting code on my Web site. Go to >http://www.excastle.com/Tyler/ and scroll to the bottom of the page, and >click "Download Tyler technology preview demo #1". > [snip] |
|
||
|
||||
|
|
|
| |
![]() |
| Thread Tools | |
| Rate This Thread | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Updating Form Controls from Separate Worker Thread - Must all code be in the same source file? | snaga.ohme@gmail.com | Microsoft Dot NET Framework Forms | 3 | 24th Jun 2007 02:25 AM |
| Moving a borderless form that contains child controls | Flyte | Microsoft Dot NET Framework Forms | 1 | 14th Feb 2007 09:07 PM |
| Hosting user controls on a separate thread. | Frosty Madness | Microsoft Dot NET Framework | 1 | 23rd Oct 2005 01:02 PM |
| Keyboard focus issue - form in separate thread/separate appdomain | =?Utf-8?B?REpIdWdoZXM=?= | Microsoft Dot NET Framework | 0 | 13th Mar 2005 12:07 AM |
| Controls created on one thread cannot be parented to a control on a different thread | gregbacchus@hotmail.com | Microsoft Dot NET Framework Forms | 8 | 19th Oct 2004 03:23 PM |
Powered by vBulletin®. Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2010, Crawlability, Inc. |




