开发者

A Plugin architecture in .net and handling Events

I need to write an app that that will iterate over our database, and perform various anaylsis on each record. In order to do this (partially for the learning exercise in creating plugin support) I want to use a Plugin model.

Currently, I have a simple Interface in my main app, which plugins can Implement. My app then loads all DLL's in a folder looking for ones implementing the Interface.

As you can see in the pseudo-code below, I have to keep performing a loop through all loaded plugins calling the process methods.

Sub ProcessData()
    For Each Record In MyDataSet

        For Each Plugin In MyPluginCollection
            Plugin.ProcessRecord(Record)
        Next

    Next
End Sub

If I wanted each of the plugins to fire asynchronously, how would I track when all the plugins are done?

Sub ProcessData()
    For Each Record In MyDataSet

        # Start all the plugins off on their processing task            
        For Each Plugin In MyPluginCollection
            CreateNewThreadFor Plugin.StartProcess(Record)
        Next

        # Do not start the ne开发者_Python百科xt record until this record is completed by all plugins
        Dim Complete As Boolean = False
        While Not Complete
            For Each Plugin In MyPluginCollection
                If Plugin.IsBusy Then
                    Complete = False
                End If
            Next
            DoEvents
        End While

    Next
End Sub

Or am I just opening myself up for a world of pain trying to multithread it in this way?


An alternative to using manual reset events could be:

ForEach plugin
   Create new thread for plugin
   Add thread to thread list
   Start the plugin method execution
Next

ForEach Thread in thread list
   Thread.Join() //blocking call until Thread is completed

With the anonymous and extension methods this can achieved with very few lines. Here's an example in C# (not tested):

List<Thread> lstThreads = new List<Thread>();
Thread objThread;

foreach(Record r in MyDataSet)
{
    lstThreads.Clear();
    MyPluginCollection.ForEach(delegate(Plugin p)
    {
        objThread = new Thread(new ThreadStart(delegate() 
        {
            p.StartProcess(Record);
        }));
        lstThreads.Add(objThread);
    });
    lstThreads.ForEach(t => t.Start());
    lstThreads.ForEach(t => t.Join());
}


Best way would be to extend your Interface with an Event "ProcessCompleted" and checking within that event if every PlugIn is ready (f.e. with a Property "ProcessInProgress").

Bobby


You want to read up on ManualResetEvents. They will do the trick. http://www.codeproject.com/KB/threads/AutoManualResetEvents.aspx

Thats not to say you aren't entering a world of pain, however.

here is an example. paste into a command line app

var r = new Random();
Action a = () => Thread.Sleep(r.Next(5000));

Action<int> process = i => //represents your plugin
{
    Console.WriteLine("Thread " + i + " started");
    Thread.Sleep(r.Next(5000));
    Console.WriteLine("Thread " + i + " finished");
};

var mres = new List<ManualResetEvent>();
for (var i = 0; i < 10; i++)
{
    var count = i;
    var mre = new ManualResetEvent(false);
    new Thread(() =>
                   {
                       process(count);
                       mre.Set();
                   }).Start();
    mres.Add(mre);
}
ManualResetEvent.WaitAll(mres.ToArray()); //try commenting this line
Console.WriteLine("All threads finished. Press enter to continue");
Console.ReadLine();
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜