2

I have some sample source code below with 2 lock statements. During my test run I click 'r1RefreshButton' to put showReport1 method into a forever loop. Then I click 'r2RefereshButton' to check if lock is doing as intended.

I found out that the lock on showReport2 does not really lock. Did I miss something?

public partial class TestReportsForm : Form
{
    private static readonly Object thisLock = new Object();

    public TestReportsForm() { InitializeComponent(); }

    private void showReport1()
    {
        lock (thisLock)
        {
            r1RefreshButton.Enabled = false;
            try
            {
                // while loop is used to simulate long process
                while (true)
                {
                    Application.DoEvents();
                }
            }
            catch (Exception ex)
            {
                String errorMessage = "Error encountered\n\n" +
                       "Error details: \n" +
                       ex.Message;
                MessageBox.Show(this, errorMessage, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                r1RefreshButton.Enabled = true;
            }
        }
    }

    private void r1RefreshButton_Click(object sender, EventArgs e)
    {
        showReport1();
    }

    private void showReport2()
    {
        lock (thisLock)
        {
            r2RefreshButton.Enabled = false;
            try
            {
                Application.DoEvents();
                // long process here
            }
            catch (Exception ex)
            {
                String errorMessage = "Error encountered\n\n" +
                       "Error details: \n" +
                       ex.Message;
                MessageBox.Show(this, errorMessage, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                r2RefreshButton.Enabled = true;
            }
        }
    }

    private void r2RefreshButton_Click(object sender, EventArgs e)
    {
        showReport2();
    }
}    

EDIT: I found similar topic from C# Locking from events

4

3 回答 3

5

这两个函数都在同一个线程上运行。锁在线程级持有。

所以在 GUI 线程上运行的所有代码都“拥有”锁。

在此处阅读更多信息:http: //msdn.microsoft.com/en-us/library/c5kehkcz.aspx

于 2013-09-09T04:36:05.840 回答
1

如果您打算让“showReport2()”中的过程等到showReport1() ”完成,您可以使用AutoResetEvent。' showReport2() ' 将使用WaitOne()而不是 lock(),并且showReport1()将调用Set()以表示它已完成。

于 2013-09-09T06:13:18.033 回答
0

根据您的要求,我将使用 AutoResetEvent,在您的“ShowReport2”中等待设置事件,因此当您的“ShowReport1()”完成时,它会调用 AutoResetEvent 上的设置。这将使您的“ShowReport2”等到您的“ShowReport1”完成。AutoResetEvent 用于同步不同的线程。在 AutoResetEvent 的构造函数中传入 false ,因此在第一次运行时不会设置它。

http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx

于 2013-09-09T21:59:40.503 回答