【问题标题】:Simple semaphore implementation with form application带有表单应用程序的简单信号量实现
【发布时间】:2013-05-04 10:49:40
【问题描述】:

我想为我的作业展示一个针对特定问题的信号量应用示例。 我在我的 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();
    }
 }   

}

【问题讨论】:

    标签: c# semaphore


    【解决方案1】:

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

    试试这个:

    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);

    您正在初始化一个新的信号量而从未释放它。

    【讨论】:

    • 谢谢 Jason,我已经按照你说的做了,但现在银行账户功能无法使用。即使我在线程休眠期间多次单击,银行帐户功能也必须运行一次。
    • 更改为new Semaphore(0, 1) 将使得没有线程可以获取信号量。
    • 我用“if (semafor.WaitOne(0))”尝试了“Semaphore semafor=new Semaphore(1,1)”,没问题。如果信号量从 1 开始,它就可以工作。
    【解决方案2】:

    这听起来确实不适合使用信号量。如果我没看错的话,您的问题定义表明这三个按钮是互斥的:按下其中任何一个按钮都会使 所有 按钮在 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 释放信号量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-29
      • 1970-01-01
      • 2012-02-06
      相关资源
      最近更新 更多