all groups > dotnet general > march 2004 >
You're in the dotnet general group:
Event enqueing in PostMessage style
dotnet general:
Wouldn't the obvious answer be to raise the event at the end of the method? -Brian [quoted text, click to view] "John Lafrowda" <laa.laa@laa.com> wrote in message news:c4f5kj$9pt$1@news.uni-stuttgart.de... > Dear all, > > I'm currently having some trouble with the event mechanisms in the .net > framework. What I am looking for is a way to schedule events like it is done > with PostMessage in the WinAPI: When I raise an event, the raising code > should be continued. The scheduled event should just be called after > execution of the current function has terminated. In WinAPI programming, > this could be done by posting a message through PostMessage which would be > invoked not earlier as the calling thread returns to the central message > loop. > The .net framework, however, handles events more in a "SendMessage" style, > meaning that the event handler is called immediately and interrupts the > calling code. > > Cosider the following simple example in VB.net (the mechanism would be > slightly different in C# as the RaiseEvent statement is missing here - the > effect is nevertheless the same with C# techniques): > > Provide a form class (Form1) with a single button (Button1) on it: > ================================================================== > Public Class Form1 > Inherits System.Windows.Forms.Form > > [#Region " Windows Form Designer generated code "] > > Private WithEvents MyEventObj As New MyEventClass > > Private Sub MyHandler() Handles MyEventObj.MyEvent > MsgBox("During Event") > End Sub > > Private Sub Button1_Click(ByVal sender As System.Object, _ > ByVal e As System.EventArgs) Handles > Button1.Click > MsgBox("Before Call") > MyEventObj.RaiseIt() > MsgBox("After Call") > End Sub > End Class > > ================================================================== > > In addition, the MyEventClass is needed with following contents: > ================================================================== > Public Class MyEventClass > > Public Event MyEvent() > > Public Sub RaiseIt() > RaiseEvent MyEvent() > End Sub > End Class > > ================================================================== > > Now, the message boxes are appearing in the sequence "Before Call" -> > "During Event" -> "After Call", where I would like to see the sequence > "Before Call" -> "After Call" -> "During Event". > Probably the .net event model is the wrong way to go, but I don't see any > other at the moment except for going back to the WinAPI with PostMessage, > which does not provide the features of managed code (and object/contents > transmission) and is thus not exactly what I want, either. > > Maybe I don't see the obvious here... Any solutions? > > Best regards, > > John > >
To me, it almost sounds like you just want to do an asyncronous call, correct? (bear with me, I'm not a winapi guy). You could always raise the event on a separate thread if that's all you want to do. -Brian [quoted text, click to view] "John Lafrowda" <laa.laa@laa.com> wrote in message news:c4ffr4$91g$1@news.uni-stuttgart.de... > Dear Brian, > > the actual problem is a bit more complicated than the given example. So the > constraint is really to finalise the calling method before entering the > event handler - just like WinAPI coders [like me] would do it by > PostMessage. > > Maybe the answer is less obvious than I thought... > > Thanks, > > John > > > "Brian Newtz" <anonymous@discussions.microsoft.com> schrieb im Newsbeitrag > news:OBHj#s2FEHA.3568@tk2msftngp13.phx.gbl... > > Wouldn't the obvious answer be to raise the event at the end of the > method? > > > > -Brian > > > > > > "John Lafrowda" <laa.laa@laa.com> wrote in message > > news:c4f5kj$9pt$1@news.uni-stuttgart.de... > > > Dear all, > > > > > > I'm currently having some trouble with the event mechanisms in the ..net > > > framework. What I am looking for is a way to schedule events like it is > > done > > > with PostMessage in the WinAPI: When I raise an event, the raising code > > > should be continued. The scheduled event should just be called after > > > execution of the current function has terminated. In WinAPI programming, > > > this could be done by posting a message through PostMessage which would > be > > > invoked not earlier as the calling thread returns to the central message > > > loop. > > > The .net framework, however, handles events more in a "SendMessage" > style, > > > meaning that the event handler is called immediately and interrupts the > > > calling code. > > > > > > Cosider the following simple example in VB.net (the mechanism would be > > > slightly different in C# as the RaiseEvent statement is missing here - > the > > > effect is nevertheless the same with C# techniques): > > > > > > Provide a form class (Form1) with a single button (Button1) on it: > > > ================================================================== > > > Public Class Form1 > > > Inherits System.Windows.Forms.Form > > > > > > [#Region " Windows Form Designer generated code "] > > > > > > Private WithEvents MyEventObj As New MyEventClass > > > > > > Private Sub MyHandler() Handles MyEventObj.MyEvent > > > MsgBox("During Event") > > > End Sub > > > > > > Private Sub Button1_Click(ByVal sender As System.Object, _ > > > ByVal e As System.EventArgs) Handles > > > Button1.Click > > > MsgBox("Before Call") > > > MyEventObj.RaiseIt() > > > MsgBox("After Call") > > > End Sub > > > End Class > > > > > > ================================================================== > > > > > > In addition, the MyEventClass is needed with following contents: > > > ================================================================== > > > Public Class MyEventClass > > > > > > Public Event MyEvent() > > > > > > Public Sub RaiseIt() > > > RaiseEvent MyEvent() > > > End Sub > > > End Class > > > > > > ================================================================== > > > > > > Now, the message boxes are appearing in the sequence "Before Call" -> > > > "During Event" -> "After Call", where I would like to see the sequence > > > "Before Call" -> "After Call" -> "During Event". > > > Probably the .net event model is the wrong way to go, but I don't see > any > > > other at the moment except for going back to the WinAPI with > PostMessage, > > > which does not provide the features of managed code (and object/contents > > > transmission) and is thus not exactly what I want, either. > > > > > > Maybe I don't see the obvious here... Any solutions? > > > > > > Best regards, > > > > > > John > > > > > > > > > > > >
Dear all, I'm currently having some trouble with the event mechanisms in the .net framework. What I am looking for is a way to schedule events like it is done with PostMessage in the WinAPI: When I raise an event, the raising code should be continued. The scheduled event should just be called after execution of the current function has terminated. In WinAPI programming, this could be done by posting a message through PostMessage which would be invoked not earlier as the calling thread returns to the central message loop. The .net framework, however, handles events more in a "SendMessage" style, meaning that the event handler is called immediately and interrupts the calling code. Cosider the following simple example in VB.net (the mechanism would be slightly different in C# as the RaiseEvent statement is missing here - the effect is nevertheless the same with C# techniques): Provide a form class (Form1) with a single button (Button1) on it: ================================================================== Public Class Form1 Inherits System.Windows.Forms.Form [#Region " Windows Form Designer generated code "] Private WithEvents MyEventObj As New MyEventClass Private Sub MyHandler() Handles MyEventObj.MyEvent MsgBox("During Event") End Sub Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click MsgBox("Before Call") MyEventObj.RaiseIt() MsgBox("After Call") End Sub End Class ================================================================== In addition, the MyEventClass is needed with following contents: ================================================================== Public Class MyEventClass Public Event MyEvent() Public Sub RaiseIt() RaiseEvent MyEvent() End Sub End Class ================================================================== Now, the message boxes are appearing in the sequence "Before Call" -> "During Event" -> "After Call", where I would like to see the sequence "Before Call" -> "After Call" -> "During Event". Probably the .net event model is the wrong way to go, but I don't see any other at the moment except for going back to the WinAPI with PostMessage, which does not provide the features of managed code (and object/contents transmission) and is thus not exactly what I want, either. Maybe I don't see the obvious here... Any solutions? Best regards, John
Dear Brian, the actual problem is a bit more complicated than the given example. So the constraint is really to finalise the calling method before entering the event handler - just like WinAPI coders [like me] would do it by PostMessage. Maybe the answer is less obvious than I thought... Thanks, John "Brian Newtz" <anonymous@discussions.microsoft.com> schrieb im Newsbeitrag news:OBHj#s2FEHA.3568@tk2msftngp13.phx.gbl... [quoted text, click to view] > Wouldn't the obvious answer be to raise the event at the end of the method? > > -Brian > > > "John Lafrowda" <laa.laa@laa.com> wrote in message > news:c4f5kj$9pt$1@news.uni-stuttgart.de... > > Dear all, > > > > I'm currently having some trouble with the event mechanisms in the .net > > framework. What I am looking for is a way to schedule events like it is > done > > with PostMessage in the WinAPI: When I raise an event, the raising code > > should be continued. The scheduled event should just be called after > > execution of the current function has terminated. In WinAPI programming, > > this could be done by posting a message through PostMessage which would be > > invoked not earlier as the calling thread returns to the central message > > loop. > > The .net framework, however, handles events more in a "SendMessage" style, > > meaning that the event handler is called immediately and interrupts the > > calling code. > > > > Cosider the following simple example in VB.net (the mechanism would be > > slightly different in C# as the RaiseEvent statement is missing here - the > > effect is nevertheless the same with C# techniques): > > > > Provide a form class (Form1) with a single button (Button1) on it: > > ================================================================== > > Public Class Form1 > > Inherits System.Windows.Forms.Form > > > > [#Region " Windows Form Designer generated code "] > > > > Private WithEvents MyEventObj As New MyEventClass > > > > Private Sub MyHandler() Handles MyEventObj.MyEvent > > MsgBox("During Event") > > End Sub > > > > Private Sub Button1_Click(ByVal sender As System.Object, _ > > ByVal e As System.EventArgs) Handles > > Button1.Click > > MsgBox("Before Call") > > MyEventObj.RaiseIt() > > MsgBox("After Call") > > End Sub > > End Class > > > > ================================================================== > > > > In addition, the MyEventClass is needed with following contents: > > ================================================================== > > Public Class MyEventClass > > > > Public Event MyEvent() > > > > Public Sub RaiseIt() > > RaiseEvent MyEvent() > > End Sub > > End Class > > > > ================================================================== > > > > Now, the message boxes are appearing in the sequence "Before Call" -> > > "During Event" -> "After Call", where I would like to see the sequence > > "Before Call" -> "After Call" -> "During Event". > > Probably the .net event model is the wrong way to go, but I don't see any > > other at the moment except for going back to the WinAPI with PostMessage, > > which does not provide the features of managed code (and object/contents > > transmission) and is thus not exactly what I want, either. > > > > Maybe I don't see the obvious here... Any solutions? > > > > Best regards, > > > > John > > > > > >
[quoted text, click to view] > To me, it almost sounds like you just want to do an asyncronous call, > correct? (bear with me, I'm not a winapi guy). You could always raise the > event on a separate thread if that's all you want to do.
More or less, an asynchronous call performed by another thread is exactly what I want to prevent. Situation is as follows: My programme structure consists of a central module loading several plug-ins during run-time. these plug-ins provides service code which may be called by the thread of the central module. If operation of the services can be concluded in short time, the thread of the central module enters, performs the service operations and leaves again. In case, operation will take long time, the plug-in services may start their own threads after which the main thread can return immediately. Now, the event is needed to inform the main module that operations of a service of any kind have finished. From the concept of exceptions, I've expected that I could pack all the results of the services in objects that are passed to a RaiseEvent function (or similar C#-construct). Furthermore, I've expected that these events are queued and invoked by the cental module's thread only. Thus, I've expected this could be a way to synchronise the receipt of service results. If this does not work, I could manually create a results-queue and hack in some PostMessage that notifies the central module of the arrival of service results in the queue. My main question, however, may be reformulated much simpler: Where is the point in using events and RaiseEvent if you could invoke the corresponding event handler by invoking the associated handler function. From what I see now, this would result in the same application flow which may easily result in conflicts like re-entrant code. The only advantage from events would then be that modules may offer standardised event interfaces that may be imported in different software solutions when re-using the object. The exectution sequence of directly jumping to the event handler code, however, appears very unpracticable to most the situations where I would use events. Any further ideas? Best regards, Peter
[quoted text, click to view] > To me, it almost sounds like you just want to do an asyncronous call, > correct? (bear with me, I'm not a winapi guy). You could always raise the > event on a separate thread if that's all you want to do.
More or less, an asynchronous call performed by another thread is exactly what I want to prevent. Situation is as follows: My programme structure consists of a central module loading several plug-ins during run-time. these plug-ins provides service code which may be called by the thread of the central module. If operation of the services can be concluded in short time, the thread of the central module enters, performs the service operations and leaves again. In case, operation will take long time, the plug-in services may start their own threads after which the main thread can return immediately. Now, the event is needed to inform the main module that operations of a service of any kind have finished. From the concept of exceptions, I've expected that I could pack all the results of the services in objects that are passed to a RaiseEvent function (or similar C#-construct). Furthermore, I've expected that these events are queued and invoked by the cental module's thread only. Thus, I've expected this could be a way to synchronise the receipt of service results. If this does not work, I could manually create a results-queue and hack in some PostMessage that notifies the central module of the arrival of service results in the queue. My main question, however, may be reformulated much simpler: Where is the point in using events and RaiseEvent if you could invoke the corresponding event handler by invoking the associated handler function. From what I see now, this would result in the same application flow which may easily result in conflicts like re-entrant code. The only advantage from events would then be that modules may offer standardised event interfaces that may be imported in different software solutions when re-using the object. The exectution sequence of directly jumping to the event handler code, however, appears very unpracticable to most the situations where I would use events. Any further ideas? Best regards, John
Ok, if I understand you correctly, you have a main module that is the subscriber to the events of the service modules (aka plugins). You want the events fired by the services to be received by the main module in order (i.e. - always handled by the main thread of the main module). Here's a bare bones implementation of a sample windows forms app that does what you want. (Hopefully all of the code won't have to formatting butchered TOO much :) First, the form.cs file that has the main windows form. In particular, pay attention to MyHandler_MethodFinished and MainThreadhandler: using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.Threading; namespace EventSyncronizationWindows { /// <summary> /// Summary description for Form1. /// </summary> public class Form1 : System.Windows.Forms.Form { private System.Windows.Forms.RichTextBox rtbOutput; private System.Windows.Forms.Button btnLoadPlugins; /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.Container components = null; public Form1() { // // Required for Windows Form Designer support // InitializeComponent(); Thread.CurrentThread.Name = "Main Thread"; } private void btnLoadPlugins_Click(object sender, System.EventArgs e) { PlugInA a = new PlugInA(); PlugInB b = new PlugInB(); a.MethodFinished += new MethodFinishedDelegate(MyHandler_MethodFinished); b.MethodFinished += new MethodFinishedDelegate(MyHandler_MethodFinished); rtbOutput.AppendText("Calling PluginA MethodShort\n"); a.MethodShort(); rtbOutput.AppendText("Calling PluginB MethodShort\n"); b.MethodShort(); rtbOutput.AppendText("Calling PluginA MethodLong\n"); a.MethodLong(); rtbOutput.AppendText("Calling PluginA MethodLong\n"); b.MethodLong(); } private void MyHandler_MethodFinished(object sender, MethodFinishedArgs e) { this.Invoke(new MethodFinishedDelegate(this.MainThreadhandler), new object[] {sender, e}); } private void MainThreadhandler(object sender, MethodFinishedArgs e) { string methodFinished = (string)e.EventData.Data; rtbOutput.AppendText(Thread.CurrentThread.Name + " : " + methodFinished + "\n"); } /// <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.rtbOutput = new System.Windows.Forms.RichTextBox(); this.btnLoadPlugins = new System.Windows.Forms.Button(); this.SuspendLayout(); // // rtbOutput // this.rtbOutput.Dock = System.Windows.Forms.DockStyle.Top; this.rtbOutput.Location = new System.Drawing.Point(0, 0); this.rtbOutput.Name = "rtbOutput"; this.rtbOutput.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.ForcedBoth; this.rtbOutput.Size = new System.Drawing.Size(488, 360); this.rtbOutput.TabIndex = 0; this.rtbOutput.Text = ""; this.rtbOutput.WordWrap = false; // // btnLoadPlugins // this.btnLoadPlugins.Location = new System.Drawing.Point(400, 376); this.btnLoadPlugins.Name = "btnLoadPlugins"; this.btnLoadPlugins.TabIndex = 1; this.btnLoadPlugins.Text = "Load Plugins"; this.btnLoadPlugins.Click += new System.EventHandler(this.btnLoadPlugins_Click); // // Form1 // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(488, 414); this.Controls.Add(this.btnLoadPlugins); this.Controls.Add(this.rtbOutput); this.Name = "Form1"; this.Text = "Form1"; this.ResumeLayout(false); } #endregion /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.Run(new Form1()); } } } END CODE FOR FORM. Now, here's the code for the simplified plugin classes, delegates, eventargs, etc: using System; using System.Threading; namespace EventSyncronizationWindows { delegate void MethodFinishedDelegate(object sender, MethodFinishedArgs e); class PlugInA { public event MethodFinishedDelegate MethodFinished; public void MethodShort() { for(int i = 0; i < 100; i++) { } this.OnMethodFinished(new MethodFinishedArgs(new EventData("PluginA - MethodShortFinished"))); } public void MethodLong() { ThreadStart ts = new ThreadStart(this.AsyncMethod); Thread t = new Thread(ts); t.Name = "PluginA Thread"; t.Start(); } private void AsyncMethod() { DateTime future = DateTime.Now.AddSeconds(10); while (DateTime.Now < future) { } this.OnMethodFinished(new MethodFinishedArgs(new EventData("PluginA - AsyncMethodFinished"))); } protected virtual void OnMethodFinished(MethodFinishedArgs e) { if (this.MethodFinished != null) { this.MethodFinished(this, e); } } } class PlugInB { public event MethodFinishedDelegate MethodFinished; public void MethodShort() { for(int i = 0; i < 100; i++) { } this.OnMethodFinished(new MethodFinishedArgs(new EventData("PluginB - MethodShortFinished"))); } public void MethodLong() { ThreadStart ts = new ThreadStart(this.AsyncMethod); Thread t = new Thread(ts); t.Name = "PluginB Thread"; t.Start(); } private void AsyncMethod() { DateTime future = DateTime.Now.AddSeconds(5); while (DateTime.Now < future) { } this.OnMethodFinished(new MethodFinishedArgs(new EventData("PluginB - AsyncMethodFinished"))); } protected virtual void OnMethodFinished(MethodFinishedArgs e) { if (this.MethodFinished != null) { this.MethodFinished(this, e); } } } class EventData { private object data; public EventData(object data) { this.data = data; } public object Data { get { return this.data; } } } class MethodFinishedArgs : EventArgs { private EventData eventData; public MethodFinishedArgs(EventData arbitraryEventData) { this.eventData = arbitraryEventData; } public EventData EventData { get { return this.eventData; } } } } END CODE. I know this is a bunch to chew on, but basically, you can copy the form code to a cs file, then copy the plugin classes and such to another file, plop them in a solution and build it, and you will see that the
Glad I could help! -Brian [quoted text, click to view] "John Lafrowda" <laa.laa@laa.com> wrote in message news:c4kb77$j6o$1@news.uni-stuttgart.de... > Thanks a lot! > > The code works perfectly and does what I want. As I find it a bit too > complex for what I am doing, I tried to modify some bits and now I get a > similar procedure where I use only delegate functions without the need for > events. > My main problem was obviously derived from missunderstanding the "invoke" > method, which is now clear to me from what I've seen in your code. It is > exactly this feature that I need to make the server's thread handling a data > delivered by the plug-in threads and to prevent the plug-ins' threads > entering the server's binary code. > > So far for the big knot in my head... > > Best regards, > > John > > > "Brian Newtz" <anonymous@discussions.microsoft.com> schrieb im Newsbeitrag > news:eoLlFhMGEHA.2052@TK2MSFTNGP12.phx.gbl... > > Ok, if I understand you correctly, you have a main module that is the > > subscriber to the events of the service modules (aka plugins). You want > the > > events fired by the services to be received by the main module in order > > (i.e. - always handled by the main thread of the main module). > > > > Here's a bare bones implementation of a sample windows forms app that does > > what you want. (Hopefully all of the code won't have to formatting > butchered > > TOO much :) > > > > First, the form.cs file that has the main windows form. In particular, pay > > attention to MyHandler_MethodFinished and MainThreadhandler: > > > > using System; > > using System.Drawing; > > using System.Collections; > > using System.ComponentModel; > > using System.Windows.Forms; > > using System.Data; > > using System.Threading; > > > > namespace EventSyncronizationWindows > > { > > /// <summary> > > /// Summary description for Form1. > > /// </summary> > > public class Form1 : System.Windows.Forms.Form > > { > > private System.Windows.Forms.RichTextBox rtbOutput; > > private System.Windows.Forms.Button btnLoadPlugins; > > /// <summary> > > /// Required designer variable. > > /// </summary> > > private System.ComponentModel.Container components = null; > > > > public Form1() > > { > > // > > // Required for Windows Form Designer support > > // > > InitializeComponent(); > > > > Thread.CurrentThread.Name = "Main Thread"; > > } > > > > private void btnLoadPlugins_Click(object sender, System.EventArgs e) > > { > > PlugInA a = new PlugInA(); > > PlugInB b = new PlugInB(); > > > > a.MethodFinished += new > MethodFinishedDelegate(MyHandler_MethodFinished); > > b.MethodFinished += new > MethodFinishedDelegate(MyHandler_MethodFinished); > > > > rtbOutput.AppendText("Calling PluginA MethodShort\n"); > > a.MethodShort(); > > rtbOutput.AppendText("Calling PluginB MethodShort\n"); > > b.MethodShort(); > > rtbOutput.AppendText("Calling PluginA MethodLong\n"); > > a.MethodLong(); > > rtbOutput.AppendText("Calling PluginA MethodLong\n"); > > b.MethodLong(); > > } > > > > private void MyHandler_MethodFinished(object sender, MethodFinishedArgs > e) > > { > > this.Invoke(new MethodFinishedDelegate(this.MainThreadhandler), new > > object[] {sender, e}); > > } > > > > private void MainThreadhandler(object sender, MethodFinishedArgs e) > > { > > string methodFinished = (string)e.EventData.Data; > > rtbOutput.AppendText(Thread.CurrentThread.Name + " : " + methodFinished > + > > "\n"); > > } > > > > /// <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.rtbOutput = new System.Windows.Forms.RichTextBox(); > > this.btnLoadPlugins = new System.Windows.Forms.Button(); > > this.SuspendLayout(); > > // > > // rtbOutput > > // > > this.rtbOutput.Dock = System.Windows.Forms.DockStyle.Top; > > this.rtbOutput.Location = new System.Drawing.Point(0, 0); > > this.rtbOutput.Name = "rtbOutput"; > > this.rtbOutput.ScrollBars = > > System.Windows.Forms.RichTextBoxScrollBars.ForcedBoth; > > this.rtbOutput.Size = new System.Drawing.Size(488, 360); > > this.rtbOutput.TabIndex = 0; > > this.rtbOutput.Text = ""; > > this.rtbOutput.WordWrap = false; > > // > > // btnLoadPlugins > > // > > this.btnLoadPlugins.Location = new System.Drawing.Point(400, 376); > > this.btnLoadPlugins.Name = "btnLoadPlugins"; > > this.btnLoadPlugins.TabIndex = 1; > > this.btnLoadPlugins.Text = "Load Plugins"; > > this.btnLoadPlugins.Click += new > > System.EventHandler(this.btnLoadPlugins_Click); > > // > > // Form1 > > // > > this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); > > this.ClientSize = new System.Drawing.Size(488, 414); > > this.Controls.Add(this.btnLoadPlugins); > > this.Controls.Add(this.rtbOutput); > > this.Name = "Form1"; > > this.Text = "Form1"; > > this.ResumeLayout(false); > > > > } > > #endregion > > > > /// <summary> > > /// The main entry point for the application. > > /// </summary> > > [STAThread] > > static void Main() > > { > > Application.Run(new Form1()); > > } > > } > > } > > > > END CODE FOR FORM. Now, here's the code for the simplified plugin classes, > > delegates, eventargs, etc: > > > > using System; > > using System.Threading; > > > > namespace EventSyncronizationWindows > > { > > delegate void MethodFinishedDelegate(object sender, MethodFinishedArgs > e); > > > > class PlugInA > > { > > public event MethodFinishedDelegate MethodFinished; > > > > public void MethodShort() > > { > > for(int i = 0; i < 100; i++) > > { > > } > > > > this.OnMethodFinished(new MethodFinishedArgs(new EventData("PluginA - > > MethodShortFinished"))); > > } > > > > public void MethodLong() > > { > > ThreadStart ts = new ThreadStart(this.AsyncMethod); > > Thread t = new Thread(ts); > > > > t.Name = "PluginA Thread"; > > t.Start(); > > } > > > > private void AsyncMethod() > > { > > DateTime future = DateTime.Now.AddSeconds(10); > > while (DateTime.Now < future) > > { > > } > > > > this.OnMethodFinished(new MethodFinishedArgs(new EventData("PluginA - > > AsyncMethodFinished"))); > > } > >
Thanks a lot! The code works perfectly and does what I want. As I find it a bit too complex for what I am doing, I tried to modify some bits and now I get a similar procedure where I use only delegate functions without the need for events. My main problem was obviously derived from missunderstanding the "invoke" method, which is now clear to me from what I've seen in your code. It is exactly this feature that I need to make the server's thread handling a data delivered by the plug-in threads and to prevent the plug-ins' threads entering the server's binary code. So far for the big knot in my head... Best regards, John "Brian Newtz" <anonymous@discussions.microsoft.com> schrieb im Newsbeitrag news:eoLlFhMGEHA.2052@TK2MSFTNGP12.phx.gbl... [quoted text, click to view] > Ok, if I understand you correctly, you have a main module that is the > subscriber to the events of the service modules (aka plugins). You want the > events fired by the services to be received by the main module in order > (i.e. - always handled by the main thread of the main module). > > Here's a bare bones implementation of a sample windows forms app that does > what you want. (Hopefully all of the code won't have to formatting butchered > TOO much :) > > First, the form.cs file that has the main windows form. In particular, pay > attention to MyHandler_MethodFinished and MainThreadhandler: > > using System; > using System.Drawing; > using System.Collections; > using System.ComponentModel; > using System.Windows.Forms; > using System.Data; > using System.Threading; > > namespace EventSyncronizationWindows > { > /// <summary> > /// Summary description for Form1. > /// </summary> > public class Form1 : System.Windows.Forms.Form > { > private System.Windows.Forms.RichTextBox rtbOutput; > private System.Windows.Forms.Button btnLoadPlugins; > /// <summary> > /// Required designer variable. > /// </summary> > private System.ComponentModel.Container components = null; > > public Form1() > { > // > // Required for Windows Form Designer support > // > InitializeComponent(); > > Thread.CurrentThread.Name = "Main Thread"; > } > > private void btnLoadPlugins_Click(object sender, System.EventArgs e) > { > PlugInA a = new PlugInA(); > PlugInB b = new PlugInB(); > > a.MethodFinished += new MethodFinishedDelegate(MyHandler_MethodFinished); > b.MethodFinished += new MethodFinishedDelegate(MyHandler_MethodFinished); > > rtbOutput.AppendText("Calling PluginA MethodShort\n"); > a.MethodShort(); > rtbOutput.AppendText("Calling PluginB MethodShort\n"); > b.MethodShort(); > rtbOutput.AppendText("Calling PluginA MethodLong\n"); > a.MethodLong(); > rtbOutput.AppendText("Calling PluginA MethodLong\n"); > b.MethodLong(); > } > > private void MyHandler_MethodFinished(object sender, MethodFinishedArgs e) > { > this.Invoke(new MethodFinishedDelegate(this.MainThreadhandler), new > object[] {sender, e}); > } > > private void MainThreadhandler(object sender, MethodFinishedArgs e) > { > string methodFinished = (string)e.EventData.Data; > rtbOutput.AppendText(Thread.CurrentThread.Name + " : " + methodFinished + > "\n"); > } > > /// <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.rtbOutput = new System.Windows.Forms.RichTextBox(); > this.btnLoadPlugins = new System.Windows.Forms.Button(); > this.SuspendLayout(); > // > // rtbOutput > // > this.rtbOutput.Dock = System.Windows.Forms.DockStyle.Top; > this.rtbOutput.Location = new System.Drawing.Point(0, 0); > this.rtbOutput.Name = "rtbOutput"; > this.rtbOutput.ScrollBars = > System.Windows.Forms.RichTextBoxScrollBars.ForcedBoth; > this.rtbOutput.Size = new System.Drawing.Size(488, 360); > this.rtbOutput.TabIndex = 0; > this.rtbOutput.Text = ""; > this.rtbOutput.WordWrap = false; > // > // btnLoadPlugins > // > this.btnLoadPlugins.Location = new System.Drawing.Point(400, 376); > this.btnLoadPlugins.Name = "btnLoadPlugins"; > this.btnLoadPlugins.TabIndex = 1; > this.btnLoadPlugins.Text = "Load Plugins"; > this.btnLoadPlugins.Click += new > System.EventHandler(this.btnLoadPlugins_Click); > // > // Form1 > // > this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); > this.ClientSize = new System.Drawing.Size(488, 414); > this.Controls.Add(this.btnLoadPlugins); > this.Controls.Add(this.rtbOutput); > this.Name = "Form1"; > this.Text = "Form1"; > this.ResumeLayout(false); > > } > #endregion > > /// <summary> > /// The main entry point for the application. > /// </summary> > [STAThread] > static void Main() > { > Application.Run(new Form1()); > } > } > } > > END CODE FOR FORM. Now, here's the code for the simplified plugin classes, > delegates, eventargs, etc: > > using System; > using System.Threading; > > namespace EventSyncronizationWindows > { > delegate void MethodFinishedDelegate(object sender, MethodFinishedArgs e); > > class PlugInA > { > public event MethodFinishedDelegate MethodFinished; > > public void MethodShort() > { > for(int i = 0; i < 100; i++) > { > } > > this.OnMethodFinished(new MethodFinishedArgs(new EventData("PluginA - > MethodShortFinished"))); > } > > public void MethodLong() > { > ThreadStart ts = new ThreadStart(this.AsyncMethod); > Thread t = new Thread(ts); > > t.Name = "PluginA Thread"; > t.Start(); > } > > private void AsyncMethod() > { > DateTime future = DateTime.Now.AddSeconds(10); > while (DateTime.Now < future) > { > } > > this.OnMethodFinished(new MethodFinishedArgs(new EventData("PluginA - > AsyncMethodFinished"))); > } > > protected virtual void OnMethodFinished(MethodFinishedArgs e) > { > if (this.MethodFinished != null) > { > this.MethodFinished(this, e); > } > } > } > > class PlugInB > { > public event MethodFinishedDelegate MethodFinished; > > public void MethodShort() > { > for(int i = 0; i < 100; i++) > { > } > > this.OnMethodFinished(new MethodFinishedArgs(new EventData("PluginB - > MethodShortFinished"))); > } > > public void MethodLong() > { > ThreadStart ts = new ThreadStart(this.AsyncMethod);
Don't see what you're looking for? Try a search.
|
|
|