我正在使用 C# 和 WPF 在 Visual Studio 2015 上开发一个项目。有时我使用关闭命令退出正在运行的项目,有时使用停止调试按钮。问题是,经过几次测试后,我的 PC 开始变热,风扇发出噪音。我必须退出 Visual Studio 才能让机器平静下来。
所以我有问题:
- 如何查看测试后未结束的线程?
- 当我认识他们时,如何正确地结束他们? (实际上我在
WindowClosing
时Dispose
一些线程) - 当我使用停止调试按钮时,如何确保线程正确结束?
谢谢
编辑:
有任务管理器的截图。当我开始应用程序时,CPU 从 5% 上升到 15%(或事件 25%)。 RAM 从 4GO 上升到 4.5。 当我停止应用程序时,CPU 占用率达到 45% 几秒钟,然后又回到 5%,但 RAM 达到 4.70GO 并且没有回落。
编辑2:
我在我的应用程序上建立了这种线程:
private bool isClosing = false;
public void Start()
{
isClosing = false;
ThreadPool.QueueUserWorkItem(new WaitCallback(doWorkThread));
}
public void Stop()
{
isClosing = true;
}
private AutoResetEvent endPoolStateButton = new AutoResetEvent(false);
private void doWorkThread(object sender)
{
Action action = new Action(() => doWork());
while (!isClosing)
{
Thread.Sleep(100);
this.Dispatcher.BeginInvoke(action, System.Windows.Threading.DispatcherPriority.Background);
}
endPoolStateButton.Set();
}
private void doWork()
{
/* Job performed */
}
我想知道是否有真正好的使用线程的方法?如果应用程序在未设置 isClosing = true
的情况下关闭,则 while 永远不会停止。而且线程从未真正中止?你认为这种线程会引起我所有的麻烦吗?
最佳答案
这里是 my solution如何以优雅的方式停止线程。希望代码清晰。我用 CancellationToken取消线程中的操作和ManualResetEvent等待线程取消:
namespace ElegantThreadWork
{
using System;
using System.Threading;
using System.Diagnostics;
class ThreadObject
{
public CancellationToken CancellationToken { get; private set; }
public ManualResetEvent WaitHandle { get; private set; }
public ThreadObject(CancellationToken ct, ManualResetEvent wh)
{
CancellationToken = ct;
WaitHandle = wh;
}
}
public class Program
{
static void DoWork(CancellationToken ct)
{
Console.WriteLine("Thread[{0}] started", Thread.CurrentThread.ManagedThreadId);
int i = 0;
// Check for cancellation on each iteration
while (!ct.IsCancellationRequested)
{
// Do something
Console.WriteLine("Thread[{0}]: {1}", Thread.CurrentThread.ManagedThreadId, i);
// Wait on CancellationToken. If cancel be called, WaitOne() will immediatly return control!
// You can see it by elapsed time
ct.WaitHandle.WaitOne(TimeSpan.FromSeconds(1));
i++;
}
Console.WriteLine("Thread[{0}] has been cancelled", Thread.CurrentThread.ManagedThreadId);
}
static void ThreadProc(object state)
{
ThreadObject to = (ThreadObject)state;
try
{
DoWork(to.CancellationToken);
}
finally
{
to.WaitHandle.Set();
}
}
public static void Main(string[] args)
{
TimeSpan MAX_THREAD_EXITING_TIMEOUT = TimeSpan.FromSeconds(5);
// Use for elegant thread exiting
ManualResetEvent isThreadExitedEvent = new ManualResetEvent(false);
CancellationTokenSource cts = new CancellationTokenSource();
ThreadObject threadObj = new ThreadObject(cts.Token, isThreadExitedEvent);
// Create thread
Thread thread = new Thread(ThreadProc, 0);
thread.Start(threadObj);
Console.WriteLine("Just do something in main thread");
Console.WriteLine("Bla.");
Thread.Sleep(1000);
Console.WriteLine("Bla..");
Thread.Sleep(1000);
Console.WriteLine("Bla...");
Thread.Sleep(1000);
Console.WriteLine("Thread cancelattion...");
Stopwatch sw = Stopwatch.StartNew();
// Cancel thread
cts.Cancel();
// Wait for thread exiting
var isOk = isThreadExitedEvent.WaitOne(MAX_THREAD_EXITING_TIMEOUT);
sw.Stop();
Console.WriteLine("Waiting {0} for thread exiting. Wait result: {1}. Cancelled in {2}", MAX_THREAD_EXITING_TIMEOUT, isOk, sw.Elapsed);
// If we couldn't stop thread in elegant way, just abort it
if (!isOk)
thread.Abort();
}
}
}
关于c# - 查看线程未正确结束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38521172/