使用表单应用程序的简单信号量实现

时间:2013-05-04 10:49:40

标签: c# semaphore

我想展示信号量的示例应用,以解决我的家庭作业中的特定问题。 我在C#表单中添加了3个按钮,我想显示在特定时间只有一个按钮在我的代码中执行银行帐户功能。当我在两秒钟内点击三个按钮时,银行帐户功能必须只运行一次。因为我有一个Thread.Sleep(6000)6秒钟等待银行账户功能。但我的三次点击连续按6秒间隔运行。当我连续按下三个按钮时,如何将代码更改为仅运行一次。 守则是:

命名空间semafor_form

{

public partial class Form1 : Form

   {
   Semaphore semafor=new Semaphore(1,1);

   delegate void SetTextCallback(string text);

   private void SetText(string text)
   {

       if (this.textBox2.InvokeRequired)
       {
           SetTextCallback d = new SetTextCallback(SetText);
           this.Invoke(d, new object[] { text });
       }
       else
       {
           this.textBox2.Text = text;
       }
   }

      public Form1()
    {
        InitializeComponent();

    }

    private void Form1_Load(object sender, EventArgs e)
    {

    }

    private void BankAccount()
    {
       semafor.WaitOne();
       double a = Convert.ToDouble (textBox1.Text) + Convert.ToDouble (textBox2.Text);
       Thread.Sleep(6000);
       semafor.Release(); 
       SetText(a.ToString());  
    }

    private void btnATM_Click(object sender, EventArgs e)
    {
        Thread t = new Thread(new ThreadStart(BankAccount));
        t.Start();
     }

    private void btnCOUNTER_Click(object sender, EventArgs e)
    {

        Thread t = new Thread(new ThreadStart(BankAccount));
        t.Start();
    }

    private void btnINT_Click(object sender, EventArgs e)
    {

        Thread t = new Thread(new ThreadStart(BankAccount));
        t.Start();
    }
 }   

}

2 个答案:

答案 0 :(得分:0)

我可能误解了你的问题。在使用线程时,您不希望按钮执行任何操作吗? (所以你会错过交易?)

试试这个:

private void BankAccount()
{
   if (semafor.WaitOne(0))
   {
       double a = Convert.ToDouble (textBox1.Text) + Convert.ToDouble (textBox2.Text);
       Thread.Sleep(6000);
       semafor.Release(); 
       SetText(a.ToString()); 
   } 
}

尝试将Semaphore semafor=new Semaphore(1,1);更改为Semaphore semafor=new Semaphore(0,1);

您正在初始化新信号量而不释放它。

答案 1 :(得分:0)

这听起来似乎不适合使用信号量。您的问题定义,如果我正确读取它,则表示三个按钮是互斥的:按下其中任何一个按钮将使所有按钮处于非活动状态6秒钟。您可以使用信号量,但互斥量会更合适。

无论如何,您遇到的问题是您正在等待信号量,因此当第一个事务完成时,其他一个线程将获取信号量和进程。你想要做的是尝试来获取信号量。这是一个例子。

后者的一个例子:

private void BankAccount()
{
   if (semafor.WaitOne(0))  // tries to acquire the semaphore
   {
       double a = Convert.ToDouble (textBox1.Text) + Convert.ToDouble (textBox2.Text);
       Thread.Sleep(6000);
       semafor.Release(); 
       SetText(a.ToString());
   }
}

WaitOne(0)说,"尝试获取信号量。如果它不能立即使用,则返回false。如果可用,请获取并返回true。"

您也可以在按钮处理程序中执行此操作。也就是说,让按钮处理程序获取信号量(使用WaitOne(0)),如果它不能获取信号量,则让它在不启动线程的情况下退出。如果它确实获取了信号量,启动线程并让线程proc在完成后释放信号量。