代码改变世界

让程序运行一个实例在Ireaper中实现

2011-07-23 09:11  symphony2010  阅读(265)  评论(0编辑  收藏  举报

今天尝试学习了IReaper刚启动部分,作为一个初学者,还是有一点难度

基本的目的是想搞清每个函数的功能.

程序运行会在主窗体启动前执行下列方法:

[STAThread]
     static void Main(string[] args)
     {
         //application default
         Application.EnableVisualStyles();
         Application.SetCompatibleTextRenderingDefault(false);
         //try to open an exitsing event
         if (HaveOtherInstance())
         { return; }
         //初始化一些全局参数
         GlobalInit();
         Initializer.WelcomePanel welcome = new Initializer.WelcomePanel();
         if (welcome.ShowDialog() != DialogResult.Cancel)
         {
             Application.Run(new MainForm());
         }
     }

可以先学习一下怎么让程序只运行一个实例

private static bool HaveOtherInstance()
        {
            try
            {
                EventWaitHandle globalHandler = EventWaitHandle.OpenExisting("iReaper");
                globalHandler.Set();
                return true;
            }
            catch (WaitHandleCannotBeOpenedException)
            {
                EventWaitHandle global = new EventWaitHandle(true, EventResetMode.AutoReset, "iReaper");
                Thread monitor = new Thread(new ThreadStart(delegate()
                {
                    while (true)
                    {
                        global.WaitOne();
                        Form form = Core.CoreData[CoreDataType.ApplicationForm] as Form;
                        if (form != null)
                        {
                            form.BeginInvoke(new ThreadStart(form.Show));
                        }
                    }
                }));
                monitor.IsBackground = true;
                monitor.Start();
                GC.KeepAlive(monitor);
                return false;
            }
        }

在try语句块中获得IReaper的句柄(假如该程序正在运行),如果程序在运行就会被Set()为终止状态.如果没有运行就会跳入catch语句块.

在Catch中实例化了一个EventWaitHandle,为了理解EventWaitHandle专门研究了一下微软的实例:

using System;
using System.Threading;

public class Example
{
    // The EventWaitHandle used to demonstrate the difference
    // between AutoReset and ManualReset synchronization events.
    //
    private static EventWaitHandle ewh;

    // A counter to make sure all threads are started and
    // blocked before any are released. A Long is used to show
    // the use of the 64-bit Interlocked methods.
    //
    private static long threadCount = 0;

    // An AutoReset event that allows the main thread to block
    // until an exiting thread has decremented the count.
    //
    private static EventWaitHandle clearCount = 
        new EventWaitHandle(false, EventResetMode.AutoReset);

    [MTAThread]
    public static void Main()
    {
        // Create an AutoReset EventWaitHandle.
        //
        ewh = new EventWaitHandle(false, EventResetMode.AutoReset);

        // Create and start five numbered threads. Use the
        // ParameterizedThreadStart delegate, so the thread
        // number can be passed as an argument to the Start 
        // method.
        for (int i = 0; i <= 4; i++)
        {
            Thread t = new Thread(
                new ParameterizedThreadStart(ThreadProc)
            );
            t.Start(i);
        }

        // Wait until all the threads have started and blocked.
        // When multiple threads use a 64-bit value on a 32-bit
        // system, you must access the value through the
        // Interlocked class to guarantee thread safety.
        //
        while (Interlocked.Read(ref threadCount) < 5)
        {
            Thread.Sleep(500);
        }

        // Release one thread each time the user presses ENTER,
        // until all threads have been released.
        //
        while (Interlocked.Read(ref threadCount) > 0)
        {
            Console.WriteLine("Press ENTER to release a waiting thread.");
            Console.ReadLine();

            // SignalAndWait signals the EventWaitHandle, which
            // releases exactly one thread before resetting, 
            // because it was created with AutoReset mode. 
            // SignalAndWait then blocks on clearCount, to 
            // allow the signaled thread to decrement the count
            // before looping again.
            //
            WaitHandle.SignalAndWait(ewh, clearCount);
        }
        Console.WriteLine();

        // Create a ManualReset EventWaitHandle.
        //
        ewh = new EventWaitHandle(false, EventResetMode.ManualReset);

        // Create and start five more numbered threads.
        //
        for(int i=0; i<=4; i++)
        {
            Thread t = new Thread(
                new ParameterizedThreadStart(ThreadProc)
            );
            t.Start(i);
        }

        // Wait until all the threads have started and blocked.
        //
        while (Interlocked.Read(ref threadCount) < 5)
        {
            Thread.Sleep(500);
        }

        // Because the EventWaitHandle was created with
        // ManualReset mode, signaling it releases all the
        // waiting threads.
        //
        Console.WriteLine("Press ENTER to release the waiting threads.");
        Console.ReadLine();
        ewh.Set();
        
    }

    public static void ThreadProc(object data)
    {
        int index = (int) data;

        Console.WriteLine("Thread {0} blocks.", data);
        // Increment the count of blocked threads.
        Interlocked.Increment(ref threadCount);

        // Wait on the EventWaitHandle.
        ewh.WaitOne();

        Console.WriteLine("Thread {0} exits.", data);
        // Decrement the count of blocked threads.
        Interlocked.Decrement(ref threadCount);

        // After signaling ewh, the main thread blocks on
        // clearCount until the signaled thread has 
        // decremented the count. Signal it now.
        //
        clearCount.Set();
    }
}

该实例说明了ventResetMode.AutoReset与VentResetMode.ManualReset的区别.看样子如果设置为了AutoReset模式还得

WaitHandle.SignalAndWait(ewh, clearCount);来激发一下.但在Ireaper中没找到这句代码.

Thread monitor = new Thread(new ThreadStart(delegate()
                {
                    while (true)
                    {
                        global.WaitOne();
                        Form form = Core.CoreData[CoreDataType.ApplicationForm] as Form;
                        if (form != null)
                        {
                            form.BeginInvoke(new ThreadStart(form.Show));
                        }
                    }
                }));
而且在以上代码中,该线程是一个死循环,对最后是如何退出的有疑问.

  Form form = Core.CoreData[CoreDataType.ApplicationForm] as Form;这句代码以后在做分析.

form.BeginInvoke没必要异步调用.form.Show();,何必这么复杂?也许我少考虑了什么方面(希望高手斧正).
分析下一句时发现没有中文版的解释:

GC.KeepAlive(monitor);

该句的大概意思是保证垃圾回收器不在对象的资源释放完前对资源进行回收.在MSDN中有这样一段令人费解的注释:

 GC.KeepAlive(ex);
        // The KeepAlive method need never be executed. For example,
        // if the keepAlive field is uncommented, the following line
        // of code prevents the finalizer from running first, even
        // though it is impossible for the KeepAlive method ever to
        // be executed.
        //    if (keepAlive) GC.KeepAlive(ex);
        // However, if the compiler detects that the KeepAlive can
        // never be executed, as in the following line, then it will
        // not prevent the finalizer from running first.
        //    if (false) GC.KeepAlive(ex);

这段话如果直译就是:

     KeepAlive方法应该不被执行.例如:如果keepAlive属性没被设置,下面这行代码防止析构函数提前运行,即使该方法不可能运行.

if(keepAlive)GC.KeepAlive(ex);

然而,如果编译器检测到keepAlive方法从未被执行,那么将无法防止解析器提前运行.

if (false) GC.KeepAlive(ex);//该句肯定不会执行啊,微软说这么多干嘛?

让人无法理解!!