multithreading - C# 2.0 Multi-threading with a plug-in architecture -


i have established console application in c# 2.0 uses plugin architecture. of right now, program uses basic multi-threading can run several instances. threads created , continue on until application stopped.

each instance can load own variety of plugins , configured separately. plugins inherited base plugin. system has been working charm years. plugins event driven, read various events see if called upon, if not return , let next plugin read events see if called out fire.

this system has been working years. however, further scope of multi-threading allow plugins listen events in asynchronous fashion rather synchronous. 1 of drawbacks of setup once plugin fires , work, locks out instance. when next event fired has wait previous work completed. allow next process take place.

what do, execute plugin , not have wait process end before moving on next process begin event.

i stuck .net 2.0 time being, , must find solution in framework. have looked @ numerous examples , can not find 1 meets criteria. 1 of problems each plugin has own time may take process, , there no way count track percentage plugin complete. plugins start , ends process when done. depending on parameters of event, , plugin can take range of time complete.

my question best way handle multi-threading in situation plugins executed events. have looked @ pages such http://msdn.microsoft.com/en-us/library/2e08f6yc(v=vs.80).aspx , can figure out able have entry point in event driven plugin architecture.

if has clue, appreciate it. lack of multi-threading in manner has been achilles' heel application years.

plugin base: these contain functions triggered events:

using system; using vhabot.communication;  namespace vhabot {  /// <summary> ///     plugin baseclass, must inherited plugins /// </summary> public abstract class pluginbase : marshalbyrefobject {     private bool _locked;     private string _name;     private string _internalname;     private int _version;     private string _author;     private string[] _contributors;     private string _description;     private pluginstate _defaultstate;     private string[] _dependencies;     private command[] _commands;      /// <summary>     ///     friendly display name of plugin     /// </summary>     /// <example>     ///     <code>     ///  this.name = "message of day";     ///   </code>     /// </example>     public string name     {         set         {             if (_locked)             {                 throw new exception();             }             _name = value;         }         { return _name; }     }      /// <summary>     ///     internal name of plugin     /// </summary>     /// <example>     ///     <code>     ///  this.internalname = "vhmotd";     ///   </code>     /// </example>     public string internalname     {         set         {             if (_locked)             {                 throw new exception();             }             _internalname = value.tolower();         }         { return _internalname; }     }      /// <summary>     ///     pluigin version     /// </summary>     /// <remarks>     ///     versions stored integers only. version 1.0.0 have value of 100     /// </remarks>     /// <example>     ///     <code>     /// this.version = 100;     ///  </code>     /// </example>     public int version     {         set         {             if (_locked)             {                 throw new exception();             }             _version = value;         }         { return _version; }     }      /// <summary>     ///     author of plugin     /// </summary>     /// <example>     ///     <code>     /// this.author = "vhab";     ///  </code>     /// </example>     public string author     {         set         {             if (_locked)             {                 throw new exception();             }             _author = value;         }         { return _author; }     }      /// <summary>     ///     list of contributors development of plugin.     /// </summary>     /// <example>     ///     <code>     ///  this.contributors = new string[] { "iriche", "kilmanagh" };     ///   </code>     /// </example>     public string[] contributors     {         set         {             if (_locked)             {                 throw new exception();             }             _contributors = value;         }                 {             if (_contributors != null)             {                 return _contributors;             }             return new string[0];         }     }      /// <summary>     ///     description of plugin     /// </summary>     /// <example>     ///     <code>     ///  this.description = "provides interface user view online and/or on private channel.";     ///   </code>     /// </example>     public string description     {         set         {             if (_locked)             {                 throw new exception();             }             _description = value;         }         { return _description; }     }      /// <summary>     ///     default <see cref="vhabot.pluginstate" /> of plugin     /// </summary>     /// <example>     ///     <code>     /// this.defaultstate = pluginstate.installed;     /// </code>     /// </example>     /// <seealso cref="vhabot.pluginstate" />     public pluginstate defaultstate     {         set         {             if (_locked)             {                 throw new exception();             }             _defaultstate = value;         }         { return _defaultstate; }     }      /// <summary>     ///     list of other plugins plugin dependent on function     /// </summary>     /// <remarks>     ///     plugins referred using internal names. see <see cref="vhabot.pluginbase.internalname" />     /// </remarks>     /// <example>     ///     <code>     /// this.dependencies = new string[] { "vhitems" };     /// </code>     /// </example>     public string[] dependencies     {         set         {             if (_locked)             {                 throw new exception();             }             _dependencies = value;         }                 {             if (_dependencies != null)             {                 return _dependencies;             }             return new string[0];         }     }        public command[] commands     {         set         {             if (_locked)             {                 throw new exception();             }             _commands = value;         }                 {             if (_commands != null)             {                 return _commands;             }             return new command[0];         }     }      internal void init()     {         _locked = true;     }      /// <summary>     ///     plugin has loaded in response <see cref="vhabot.shellmodules.plugins.load" />     /// </summary>     /// <param name="bot"></param>     /// ///     /// <remarks>code inside method executed when plugin loading</remarks>     public virtual void onload(botshell bot)     {     }      /// <summary>     ///     plugin has unloaded in response <see cref="vhabot.shellmodules.plugins.unload" />     /// </summary>     /// <param name="bot"></param>     /// <remarks>code inside method executed when plugin unloading</remarks>     public virtual void onunload(botshell bot)     {     }      /// <summary>     ///     plugin has installed in response <see cref="vhabot.shellmodules.plugins.install" />     /// </summary>     /// <param name="bot"></param>     public virtual void oninstall(botshell bot)     {     }      /// <summary>     ///     plugin been uninstalled in response <see cref="vhabot.shellmodules.plugins.uninstall" />     /// </summary>     /// <param name="bot"></param>     public virtual void onuninstall(botshell bot)     {     }      /// <summary>     ///     plugin has been upgraded (unused)     /// </summary>     /// <param name="bot"></param>     /// <param name="version"></param>     /// <remarks>this function not active</remarks>     public virtual void onupgrade(botshell bot, int32 version)     {     }      /// <summary>     ///     response command     /// </summary>     /// <param name="bot"></param>     /// <param name="e"></param>     public virtual void oncommand(botshell bot, commandargs e)     {     }      /// <summary>     ///     response unauthorized command     /// </summary>     /// <param name="bot"></param>     /// <param name="e"></param>     public virtual void onunauthorizedcommand(botshell bot, commandargs e)     {     }      /// <summary>     ///     response command query <see cref="vhabot.shellmodules.commands.gethelp." />     /// </summary>     /// <param name="bot"></param>     /// <param name="command"></param>     /// <returns></returns>     /// <remarks>code inside method executed when requested</remarks>     public virtual string onhelp(botshell bot, string command)     {         return null;     }      /// <summary>     ///     response custom configuration     /// </summary>     /// <param name="bot"></param>     /// <param name="key"></param>     /// <returns></returns>     public virtual string oncustomconfiguration(botshell bot, string key)     {         return null;     }      /// <summary>     ///     response plugin message     /// </summary>     /// <param name="bot"></param>     /// <param name="message"></param>     public virtual void onpluginmessage(botshell bot, pluginmessage message)     {     }      /// <summary>     ///     response bot message     /// </summary>     /// <param name="bot"></param>     /// <param name="message"></param>     public virtual void onbotmessage(botshell bot, botmessage message)     {     }      /// <summary>     ///     returns display name of bot , current version     /// </summary>     /// <returns></returns>     public override string tostring()     {         return name + " v" + version;     }      /// <summary>     ///     there no information document command     /// </summary>     /// <param name="bot"></param>     /// <param name="args"></param>     public void fireoncommand(botshell bot, commandargs args)     {         try         {             if (args.authorized)                 oncommand(bot, args);             else                 onunauthorizedcommand(bot, args);         }         catch (exception ex)         {             commandargs e = args;             var window = new richtextwindow(bot);             window.appendtitle("error report");              window.appendhighlight("error: ");             window.appendnormal(ex.message);             window.appendlinkend();             window.appendlinebreak();              window.appendhighlight("source: ");             window.appendnormal(ex.source);             window.appendlinkend();             window.appendlinebreak();              window.appendhighlight("target site: ");             window.appendnormal(ex.targetsite.tostring());             window.appendlinkend();             window.appendlinebreak();              window.appendhighlight("stack trace:");             window.appendlinebreak();             window.appendnormal(ex.stacktrace);             window.appendlinkend();             window.appendlinebreak();              bot.sendreply(e,                           "there has been error while executing command »» " +                           window.tostring("more information"));             botshell.output("[plugin execution error] " + ex);         }     } } } 

events class:

 namespace vhabot.shellmodules { /// <summary> ///     vhabot events /// </summary> public class events {     public event botstatechangedhandler botstatechangedevent;     public event channeljoineventhandler channeljoinevent;      public event userjoinchannelhandler userjoinchannelevent;     public event userleavechannelhandler userleavechannelevent;      public event userlogonhandler userlogonevent;     public event userlogoffhandler userlogoffevent;      public event privatemessagehandler privatemessageevent;     public event privatechannelmessagehandler privatechannelmessageevent;     public event channelmessagehandler channelmessageevent;      public event memberaddedhandler memberaddedevent;     public event memberremovedhandler memberremovedevent;     public event memberupdatedhandler memberupdatedevent;      public event altaddedhandler altaddedevent;     public event altremovedhandler altremovedevent;      /// <summary>     ///     message sent irc channel in response <see      cref="vhabot.botshell.sendircmessage" /> request     /// </summary>     public event ircmessagehandler ircmessageevent;      public event configurationchangedhandler configurationchangedevent;       internal void onbotstatechanged(botshell bot, botstatechangedargs e)     {         if (botstatechangedevent != null)             try             {                 botstatechangedevent(bot, e);             }             catch             {             }     }      internal void onchanneljoin(botshell bot, channeljoineventargs e)     {         if (channeljoinevent != null)             try             {                 channeljoinevent(bot, e);             }             catch             {             }     }      internal void onuserjoinchannel(botshell bot, userjoinchannelargs e)     {         if (userjoinchannelevent != null)             try             {                 userjoinchannelevent(bot, e);             }             catch             {             }     }      internal void onuserleavechannel(botshell bot, userleavechannelargs e)     {         if (userleavechannelevent != null)             try             {                 userleavechannelevent(bot, e);             }             catch             {             }     }      internal void onuserlogon(botshell bot, userlogonargs e)     {         if (userlogonevent != null)             try             {                 userlogonevent(bot, e);             }             catch             {             }     }      internal void onuserlogoff(botshell bot, userlogoffargs e)     {         if (userlogoffevent != null)             try             {                 userlogoffevent(bot, e);             }             catch             {             }     }      internal void onprivatemessage(botshell bot, privatemessageargs e)     {         if (privatemessageevent != null)             try             {                 privatemessageevent(bot, e);             }             catch             {             }     }      internal void onprivatechannelmessage(botshell bot, privatechannelmessageargs e)     {         if (privatechannelmessageevent != null)             try             {                 privatechannelmessageevent(bot, e);             }             catch             {             }     }      internal void onchannelmessage(botshell bot, channelmessageargs e)     {         if (channelmessageevent != null)             try             {                 channelmessageevent(bot, e);             }             catch             {             }     }      internal void onmemberadded(botshell bot, memberaddedargs e)     {         if (memberaddedevent != null)             try             {                 memberaddedevent(bot, e);             }             catch             {             }     }      internal void onmemberremoved(botshell bot, memberremovedargs e)     {         if (memberremovedevent != null)             try             {                 memberremovedevent(bot, e);             }             catch             {             }     }      internal void onmemberupdated(botshell bot, memberupdatedargs e)     {         if (memberupdatedevent != null)             try             {                 memberupdatedevent(bot, e);             }             catch             {             }     }      internal void onaltadded(botshell bot, altaddedargs e)     {         if (altaddedevent != null)             try             {                 altaddedevent(bot, e);             }             catch             {             }     }      internal void onaltremoved(botshell bot, altremovedargs e)     {         if (altremovedevent != null)             try             {                 altremovedevent(bot, e);             }             catch             {             }     }      internal void onconfigurationchanged(botshell bot, configurationchangedargs e)     {         if (configurationchangedevent != null)             try             {                 configurationchangedevent(bot, e);             }             catch             {             }     }      internal void onircmessage(botshell bot, ircmessageargs e)     {         if (ircmessageevent != null)         {             ircmessageevent(bot, e);         }         try         {         }         catch         {         }         }     } } 

i've got little go on description of system bit vague i'll give shot.

from description seems have plugin, say

interface iplugin {    pluginresult readandexecuteevents(events e);     // added asynchronous methods.    iasyncresult beginreadandexecuteevents(events e, asynccallback cb, object state);    pluginresult endreadandexecuteevents(iasyncresult result); } 

with

class pluginresult  {     public boolean stop;     // etc. } 

also don't seem using .net events, rather sort of event class/enumeration.

your old code seems like:

   foreach (var eventlist in readevents())            foreach (var plugin in pluginlist)               if (plugin.readandexecuteevents(eventlist).stop)                  break; 

you can make asynchronous doing like:

 foreach (var eventlist in readevents())      {         // seems want, 1 event processed @ time "instance"? block here until unlocked.         lockprocess();          var pluginindex = 0;         asynccallback handleresult = null;         handleresult = delegate(iasyncresult result)         {            if (pluginlist[pluginindex].endreadandexecuteevents(result).stop)               goto stop;             pluginindex += 1;             if (pluginindex == pluginlist.count)               goto stop;             events e = (events)result.asyncstate;             pluginlist[pluginindex].beginreadandexecuteevents(e, handleresult, e);            return;          stop:            unlockprocess();         };          pluginlist[0].beginreadandexecuteevents(eventlist, handleresult, eventlist);      } 

so in .net 2 style add beginxxx method , in asynccallback stuff. of course actual plugin multithreading/asynchronisity, if writes file using beginwrite filestream etc.

i have conveniently ignored exception handling here.

so, make whole application use asynchronisity can put code in beginrunevents method, say, following same "apm" pattern. can schedule threadpool if wish.

if not @ looking please provide more code examples/info.


Comments

Popular posts from this blog

SPSS keyboard combination alters encoding -

Add new record to the table by click on the button in Microsoft Access -

CSS3 Transition to highlight new elements created in JQuery -