gpt4 book ai didi

c# - 简单线程,为什么会这样? (C# 窗体)

转载 作者:太空狗 更新时间:2023-10-29 22:34:47 24 4
gpt4 key购买 nike

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

我只是想知道为什么这个应用程序的内存使用量在我启动、停止、启动和再次停止应用程序后不断增长。我在想,当我按下停止按钮时,我的线程实例并没有真正终止或中止。请在下面考虑我的代码,我们将不胜感激任何帮助或建议。

alt text

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();
}
}
}

最佳答案

OK,有几个建议:

使用可变标志

使您的标志可变...如果您不这样做,则线程可能永远不会看到对标志的更新。

volatile bool stopThread = false;

设置为背景

IsBackground 属性设置为 true:如果应用程序退出,它会强制终止线程,否则您可能会得到一个即使在应用程序关闭后仍然存在的“幽灵线程”。

thread1.IsBackground = true;
thread1.Start();

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

...if one thread calls Abort on another thread, the abort interrupts whatever code is running. There is a chance the thread could abort while a finally block is running, in which case the finally block is aborted. There is also a chance that a static constructor could be aborted. In rare cases, this might prevent instances of that class from being created in that application domain.

使用中断代替中止

因此,我建议您调用 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();
}
}

不要“泄漏”线程

每次单击“开始”按钮时都会泄漏线程...如果 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();
}

处理中断

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

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
}
}

我想就是这样了......哦......实际上,还有一件事:小心线程! ;)

关于c# - 简单线程,为什么会这样? (C# 窗体),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3775546/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com