Skip to main content
 首页 » 编程设计

c#之为什么 Windows 窗体应用程序 (C#) 会死锁以及如何避免死锁

2024年02月20日30yyy_WW

根据文章 Lock Up Unlocked 实现对死锁 C# Windows 窗体应用程序的更改后我仍然遇到与文章 Locked Up! 之前的代码相同的问题

也就是说,快速点击按钮几次后,应用程序挂起(变得无响应)。

为什么?
以及如何纠正它?

using System; 
using System.Windows.Forms; 
using System.Threading; 
 
namespace LockupUnlocked 
{ 
  public partial class Form1 : Form 
  { 
    public Form1() 
    { 
      InitializeComponent(); 
      _t = new Thread(new ParameterizedThreadStart(WorkerThread)); 
    } 
 
    private Thread _t; 
    private object lockObject = new object(); 
 
    private bool StopThread = false;  ////changes added to avoid deadlock 
 
    private void WorkerThread(object sender) 
    { 
      Thread.Sleep(1000); 
      //while (true) 
      while (!StopThread)//changes added to avoid deadlock 
      { 
        string result = "This is a Test"; 
        IAsyncResult aResult;////changes added to avoid deadlock 
        lock (lockObject) 
        { 
          Thread.Sleep(25); 
          //lblResult.Invoke(new MethodInvoker(delegate { lblResult.Text = result; })); 
          aResult = lblResult.BeginInvoke//changes to avoid deadlock 
            (new MethodInvoker(delegate { lblResult.Text = result; })); 
        } 
        lblResult.EndInvoke(aResult);//changes added to avoid deadlock 
        Thread.Sleep(500); 
      } 
    } 
    private void Form1_FormClosing(object sender, FormClosingEventArgs e) 
    { 
      StopThread = true; 
    } 
    private void Form1_Load(object sender, EventArgs e) 
    { 
      _t.Start(); 
    } 
 
    private void button1_Click(object sender, EventArgs e) 
    { 
      lock (lockObject)//changes added to avoid deadlock 
      { 
        lblResult.Text = "Override the Test"; 
      } 
    } 
  } 
} 

请您参考如下方法:

对我来说,这看起来像是锁争用,不一定是死锁。

你每 25 毫秒(不是 25 秒,那是 25000)迭代一次 while 循环,然后点击按钮会中断这个请求锁,它可能永远不会被给予锁,因为 sleep 在锁范围内.

如果不单击按钮,这可能看起来有效,但是,等待锁定的按钮单击将阻塞 UI 线程,导致出现“未响应”消息,因为表单没有可用的时间来绘制自身.

您实际上不需要锁定来更新文本值。当您从 Control 调用时,它只是将一条消息推送到 UI 消息队列中,该队列在 UI 线程上同步处理。您可以做的最糟糕的事情是竞争条件,它不会破坏任何共享状态。

移除锁定,代码仍应按预期工作。


我不太愿意提供任何示例代码,因为我不知道您要通过此示例实现什么目标。