簡體   English   中英

為什么Windows窗體應用程序(C#)陷入僵局以及如何避免其鎖定?

[英]Why is Windows Form app (C#) deadlocked and how to avoid its lockup?

根據文章鎖定解鎖實現對死鎖C#Windows窗體應用程序的更改后,我仍然遇到與之前的文章鎖定相同的問題

也就是說,在快速點擊按鈕幾次后,應用程序掛起(變得沒有響應)。

為什么?
以及如何糾正它?

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循環,然后單擊按鈕會中斷這個請求鎖定,因為睡眠在鎖定范圍內,所以可能永遠不會給出該鎖定。

沒有單擊按鈕這似乎可以工作,但是,等待鎖定的按鈕單擊將阻止UI線程,導致“無響應”消息出現,因為表單沒有可用的時間來繪制自己。

您實際上不需要鎖定以更新文本值。 當您從Control調用時,它只是將消息推送到UI消息隊列,該消息隊列在UI線程上同步處理。 你能做的最糟糕的是競爭條件,它不會破壞任何共享狀態。

刪除鎖定,代碼仍應按預期工作。


我對提供任何示例代碼猶豫不決,因為我不知道您要使用此示例實現什么。

使用Windows.Forms中需要GUi訪問的沖突線程的模式涉及InvokeRequired屬性和Invoke函數。 那時鎖定不是必需的。

namespace WindowsFormsApplication1
{
  using System;
  using System.Threading;
  using System.Windows.Forms;

  public partial class Form1 : Form
  {
    private Thread thread;

    public Form1()
    {
      this.InitializeComponent();
      this.thread = new Thread(this.WorkerThread);
    }

    private void WorkerThread(object sender)
    {
      Thread.Sleep(1000);

      while (true)
      {
        Thread.Sleep(25);

        this.SetText("from thread");

        Thread.Sleep(500);
      }
    }

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
      this.thread.Abort();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
      this.thread.Start();
    }

    /// <summary>
    /// This is a callback for the SetText Method.
    /// </summary>
    /// <param name="text">The text.</param>
    private delegate void SetTextCallback(string text);

    /// <summary>
    /// This sets a text. 
    /// It's thread safe, you can call this function from any thread. 
    /// If it's not called from the UI-thread, it will invoke itself
    /// on the UI thread.
    /// </summary>
    /// <param name="text">The text.</param>
    private void SetText(string text)
    {
      if (this.InvokeRequired)
      {
        this.Invoke(new SetTextCallback(this.SetText), text);
      }
      else
      {
        this.lblResult.Text = text;  
      }
    }

    private void Button1_Click(object sender, EventArgs e)
    {
      this.SetText("from button");
    }
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM