2013-02-26 1 views
1

После реализации изменений в тупиковой C# Windows Form Application в соответствии со статьей Lock Up Unlocked я все еще с той же проблемой, как и в предыдущем коде статьи Locked Up!Почему приложение Windows Form (C#) зашло в тупик и как избежать его блокировки?

То есть, при нажатии на кнопку несколько раз быстрее, приложение зависает (становится невосприимчивым).

Почему?
И как его исправить?

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"; 
     } 
    } 
    } 
} 
+0

Приходит ли приложение в конечном итоге снова реагировать? –

+0

Плохой пример, если вы спросите меня. lblResult.Text чтение/запись всегда выполняется в потоке графического интерфейса, не требующем каких-либо блокировок для запуска. – Alex

ответ

1

Шаблон для работы с конфликтующими потоками, требующий доступа к GUI в Windows.Forms включает в себя свойство 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"); 
    } 
    } 
} 
+0

Спасибо за код, хотя мое приложение не содержит 'textBox1' (там, это ярлык' lblResult') – Fulproof

+0

Я его отредактировал, пришлось воссоздать форму и остаться с именами по умолчанию. – nvoigt

3

Для меня это выглядит как конфликт блокировок, не обязательно мертвый замок.

Вы повторяете цикл while каждые 25 миллисекунд (не 25 секунд, это должно быть 25000), нажатие кнопки прерывает это, запрашивая блокировку, никогда не может быть дана эта блокировка, поскольку сон находится внутри блокировки объем.

Без нажатия кнопки это может работать, однако нажатие кнопки на ожидании блокировки блокирует поток пользовательского интерфейса, в результате чего появляется сообщение «не отвечающее», поскольку форма не имеет доступного времени для рисования сам.

На самом деле вам не нужно блокировать, чтобы обновить текстовое значение. Когда вы вызываете из Control, он просто выталкивает сообщение в очередь сообщений пользовательского интерфейса, которая обрабатывается синхронно в потоке пользовательского интерфейса. Самое худшее, что вы можете сделать, это состояние гонки, которое не повредит ни одно общее состояние.

Снимите блокировку, и код все равно будет работать так, как вы ожидаете.


Я не решаюсь предложить какой-либо образец кода, поскольку я не знаю, чего вы пытаетесь достичь с помощью этого образца.

+0

Согласен, это похоже на причину. По иронии судьбы, некоторые из кода, помеченного комментариями типа «изменения во избежание тупика», выглядят так, как правило, вызывают тупик. –

Смежные вопросы