简单的线程,为什么会发生这种情况?(C#WinForms)

yon*_*236 5 c# multithreading

我正在探索C#WinForms中的线程实现,我创建了这个简单的应用程序:

我只是想知道为什么在我启动,停止,启动和再次停止应用程序后,此应用程序的内存使用量不断增长.当我按下停止按钮时,我想到我的线程实例没有真正终止或中止.请考虑下面的代码,我们将非常感谢您提供任何帮助或建议.

替代文字

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

namespace ThreadingTest
{
    public partial class Form1 : Form
    {
        private delegate void TickerDelegate(string s);
        bool stopThread = false;
        TickerDelegate tickerDelegate1;
        Thread thread1;

        public Form1()
        {
            InitializeComponent();
            tickerDelegate1 = new TickerDelegate(SetLeftTicker);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            thread1 = new Thread(new ThreadStart(disp));
            thread1.Start();
        }

        void disp()
        {
            while (stopThread == false)
            {
                listBox1.Invoke(tickerDelegate1, new object[] { DateTime.Now.ToString() });
                Thread.Sleep(1000);
            }
        }

        private void SetLeftTicker(string s)
        {
            listBox1.Items.Add(s);
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            stopThread = true;
            if (thread1.IsAlive)
            {
                thread1.Abort();
            }
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            stopThread = false;
            thread1 = new Thread(new ThreadStart(disp));
            thread1.Start();
        }

        private void btnCheck_Click(object sender, EventArgs e)
        {
            if (thread1.IsAlive)
            {
                MessageBox.Show("Is Alive!");
            }
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            listBox1.Items.Clear();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Kir*_*ril 6

好的,有几条建议:

使用易失性标志

让你的旗帜变得不稳定......如果你不这样做,那么线程永远不会看到对旗帜的更新.

volatile bool stopThread = false;
Run Code Online (Sandbox Code Playgroud)

设置为背景

将该IsBackground属性设置为true:如果应用程序退出,它会强制终止该线程,否则即使在应用程序关闭后,您也可能会出现"ghost线程".

thread1.IsBackground = true;
thread1.Start();
Run Code Online (Sandbox Code Playgroud)

如果线程刚刚开始睡眠,那么即使在它有机会阅读标志之前你也会中止它...此外你不想使用Abort因为:

...如果一个线程在另一个线程上调用Abort,则中止将中断正在运行的任何代码.当finally块正在运行时,线程有可能中止,在这种情况下,finally块被中止.静态构造函数也有可能被中止.在极少数情况下,这可能会阻止在该应用程序域中创建该类的实例.

使用中断而不是中止

因此,我建议您调用Interrupt并处理线程内的异常,而不是使用abort :

private void btnStop_Click(object sender, EventArgs e)
{
    // have another method for re-use
    StopThread();
}

private void StopThread()
{
    stopThread = true;

    // the time out is 100 ms longer than the thread sleep
    thread1.Join(1100);

    // if the thread is still alive, then interrupt it
    if(thread1.IsAlive)
    {
        thread1.Interrupt();
    }
}
Run Code Online (Sandbox Code Playgroud)

不要"泄漏"线程

每次单击"开始"按钮时都会泄漏线程...如果thread1已经分配了一个线程并且您为其分配了另一个线程,则前一个线程将继续存在.您需要在启动另一个线程之前停止前一个线程.

private void btnStart_Click(object sender, EventArgs e)
{
    // stop the previous thread
    StopThread();

    // create a new thread
    stopThread = false;
    thread1 = new Thread(new ThreadStart(disp));
    thread1.IsBackground = true;// set it to background again
    thread1.Start();
}
Run Code Online (Sandbox Code Playgroud)

处理中断

最后,您需要处理线程中的中断:

void disp()
{
    try
    {
        while (stopThread == false)
        {
            listBox1.Invoke(tickerDelegate1, new object[] { DateTime.Now.ToString() });
            Thread.Sleep(1000);
        }
    }
    catch(ThreadInterruptedException)
    {
        // ignore the exception since the thread should terminate
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为这就是它......哦......实际上,还有一件事:线程谨慎!;)