c#中这两个锁之间的区别

时间:2011-08-03 05:43:54

标签: c# multithreading

我的WCF服务中有以下功能。此函数用于创建html页面。它使用Windows窗体的WebBrowser控件创建它。

 public Bitmap Convert(string htmlContent, int faceSheetWidth, int faceSheetHeight)
    {
        tempFileName = Guid.NewGuid().ToString().Replace("-", "");
        tempImageName = Guid.NewGuid().ToString().Replace("-", "");            
        try
        {
            width = faceSheetWidth;
            height = faceSheetHeight;

            SaveHtmlContent(htmlContent);

            //Thread m_thread = new Thread(new ThreadStart(GenerateWebSiteThumbnailImage));                
            Thread m_thread = new Thread(() =>
            {
                try
                {
                    GenerateWebSiteThumbnailImage();
                }
                catch (Exception ex)
                {
                    LoggingHelper.LogException(ex, Source.EDiscFacilityService);
                    LoggingHelper.LogException(new Exception("FaceSheet can not be created."), Source.EDiscFacilityService);
                }
            });        
            m_thread.SetApartmentState(ApartmentState.STA);
            m_thread.Start();
            m_thread.Join();
      }


 void GenerateWebSiteThumbnailImage()
    {
        WebBrowser m_WebBrowser = null;
        try
        {
            m_WebBrowser = new WebBrowser();
            m_WebBrowser.ScrollBarsEnabled = false;
            m_WebBrowser.Navigate(tempLocation);
            m_WebBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(m_WebBrowser_DocumentCompleted);
            while (m_WebBrowser.ReadyState != WebBrowserReadyState.Complete)
                Application.DoEvents();
        }
        catch {
        }
        finally
        {
            if(m_WebBrowser != null)
                m_WebBrowser.Dispose();
        }
    }


 void m_WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        WebBrowser m_WebBrowser = null;
        try
        {
            m_WebBrowser = (WebBrowser)sender;
            m_WebBrowser.ClientSize = new Size(this.width, this.height);
            m_WebBrowser.ScrollBarsEnabled = false;
            m_WebBrowser.Width = this.width;
            m_WebBrowser.Height = this.height;
            m_Bitmap = new Bitmap(m_WebBrowser.Bounds.Width, m_WebBrowser.Bounds.Height);
            m_WebBrowser.BringToFront();
            m_WebBrowser.DrawToBitmap(m_Bitmap, m_WebBrowser.Bounds);
            m_Bitmap = (Bitmap)m_Bitmap.GetThumbnailImage(width, height, null, IntPtr.Zero);
        }
        catch { }
    }

我必须锁定对GenerateWebSiteThumbnailImage的调用,以便没有2个线程可以同时访问它。我有以下几种方式: -

  1. 在类级别定义私有对象locker = new object()并按如下方式更改方法: -

    void GenerateWebSiteThumbnailImage()
    {            
        WebBrowser m_WebBrowser = null;
        try
        {
            lock (locker)
            {
                m_WebBrowser = new WebBrowser();
                m_WebBrowser.ScrollBarsEnabled = false;
                m_WebBrowser.Navigate(tempLocation);
                m_WebBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(m_WebBrowser_DocumentCompleted);
                while (m_WebBrowser.ReadyState != WebBrowserReadyState.Complete)
                    Application.DoEvents();
            }
        }
        catch {
        }
        finally
        {
            if(m_WebBrowser != null)
                m_WebBrowser.Dispose();
        }
    }
    
  2. 在GenerateWebSiteThumbnailImage函数中定义私有对象locker = new object(),并使用与第1点相同的代码。

  3. 请帮助我理解这两种方法的不同之处,这将有助于我达到预期的效果。

2 个答案:

答案 0 :(得分:1)

如果在函数内部定义了锁定对象,那么每次进入函数时都会重新创建它,因此根本不会工作 - 所有线程都会同时进入函数。您需要在类级别声明锁定对象以获取线程安全的代码。

答案 1 :(得分:1)

这些都不会起作用。您需要一个锁定对象为static,因此在每个类实例之间共享

private static object _locker = new Object();

您无法在函数中创建静态变量,因此方法#2已经完成。第一个仅在函数驻留在单例中时才有效。

如果你想要一个正确的锁,以便它只能在整个机器上调用一次,你需要一个Mutex