2014-01-26 91 views
1

對不起,沒有多線程經驗。通常我可以有效的谷歌找到我的答案,但我堅持這一個。停止一個已啓動的線程方法循環C#

我知道我可以在這裏使用背景工作,但爲了學習,我想知道如何以及如果這可以手動完成?

只是試圖啓動一個按鈕按鈕上的線程,它運行一個方法循環來向gui打印文本,但無法弄清楚如何阻止這個線程運行。從我能拿起的東西,Thread.Abort不是一個好辦法嗎?

using System; 
    using System.Collections.Generic; 
    using System.ComponentModel; 
    using System.Data; 
    using System.Drawing; 
    using System.Linq; 
    using System.Text; 
    using System.Threading.Tasks; 
    using System.Windows.Forms; 
    using System.Threading; 

    namespace ThreadStopping 
    { 
     public partial class Form1 : Form 
     { 
      public bool isRunning; 
      private static Thread neh; 

      public Form1() 
      { 
       InitializeComponent(); 
      } 

      private void Form1_Load(object sender, EventArgs e) 
      { 

      } 

      private void button1_Click(object sender, EventArgs e) 
      { 
       StartThread(); 
      } 

      private void button2_Click(object sender, EventArgs e) 
      { 
       StopThread(); 
      } 

      private void StartThread() 
      { 

       neh = new Thread(Running); 
       neh.Start(); 
       isRunning = true; 
      } 

      private void StopThread() 
      { 

        isRunning = false; 

      } 

      private void runningText(int value) 
      { 
       if (this.InvokeRequired) 
        Invoke(new runningTextDelegate(runningText),value); 
       else 
       label1.Text = value.ToString(); 
      } 

      delegate void runningTextDelegate(int value); 

      void Running() 
      { 
       while (isRunning) 
       { 
        for (int i = 0; i < 1000000; i++) 
        { 
         runningText(i); 
        } 
       } 

      } 
     } 
    } 
+0

不知道從哪裏開始,但是如果您單擊button1兩次,IsRunning和keepRunning兩種不同的動物,會發生什麼情況會出現錯誤。 –

+0

可能重複http://stackoverflow.com/questions/1865574/how-to-cancel-a-thread – wdosanjos

+0

Tony:在Start&Stop中添加了bool選項來停止它運行兩次。 thread.abort做了我在這之後的事情,所以我想我會繼續下去,直到遇到問題。 – horseman1210

回答

0

使用後臺工作線程

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
     int p = 0; 
     int high = 10000; 
     do 
     { 
      for (int i = 0; i < high; i++) 
      { 
       if (i%10 == 0 && backgroundWorker1.CancellationPending) 
        break; 

       if (i%100 == 0) // for performance purposes 
       { 
        p = (int) ((float) i/high*100); 

        backgroundWorker1.ReportProgress(p, i); 
       } 
      } 
     } while (!backgroundWorker1.CancellationPending);   

    } 

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     if(e.UserState!=null) 
     label1.Text = e.UserState.ToString(); 
     progressBar1.Value = e.ProgressPercentage; 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     backgroundWorker1.CancelAsync(); 
    } 
+0

他不想使用BeckgroundWorker。他想學習如何手動完成。 – usr

0

你是不是同步到isRunning訪問而不是-的。這是一場數據競賽。您的讀者線程可能永遠不會寫入(在指令級別上,它可能位於寄存器中)。

使用易變變量或Thread.VolatileRead/Write

您也可以鎖定對該變量的訪問權限。如果你不經常訪問它,你不應該擔心太多開銷。拳頭的關注是正確的(你一直在努力)。

除此之外,你的代碼應該工作。

Thread.Abort確實是邪惡的,因爲必須在任意指令下將代碼寫入安全的流產中。很少出現這種情況,如果您調用BCL函數,則無法控制運行的代碼。

+0

謝謝。小罐頭的蠕蟲在這裏打開。我明白你在說什麼,但試圖弄清楚另一個問題。揮發性對我來說是新的,今天才聽到,但已經跳過了鎖。 – horseman1210

+0

如果您使用線程,您突然需要了解併發問題。通常情況下,你會使用更高級的基元。在你的情況下,一個'Task'和'CancellationToken'一起可以很好的解決你的問題。但是如果你想以低級別的方式來做,你必須正確同步。任何後續問題? – usr

+0

我不是很確定爲什麼我想以低級別的方式來理解它。我首先通過學習Async等待開始了線程,但是我自己認爲自己正在走在自己的前面,並且需要先學習標準線程。我知道背景工作人員在這裏可以用來做這種事情,但是覺得這並不能教會我什麼,並且是一個簡單的出路。我也看過任務,但由於某些原因,這證明是最困難的。 – horseman1210