c# - 查看线程未正确结束

标签 c# wpf multithreading

我正在使用 C# 和 WPF 在 Visual Studio 2015 上开发一个项目。有时我使用关闭命令退出正在运行的项目,有时使用停止调试按钮。问题是,经过几次测试后,我的 PC 开始变热,风扇发出噪音。我必须退出 Visual Studio 才能让机器平静下来。

所以我有问题:

  • 如何查看测试后未结束的线程?
  • 当我认识他们时,如何正确地结束他们? (实际上我在 WindowClosingDispose 一些线程)
  • 当我使用停止调试按钮时,如何确保线程正确结束?

谢谢

编辑:

有任务管理器的截图。当我开始应用程序时,CPU 从 5% 上升到 15%(或事件 25%)。 RAM 从 4GO 上升到 4.5。 当我停止应用程序时,CPU 占用率达到 45% 几秒钟,然后又回到 5%,但 RAM 达到 4.70GO 并且没有回落。

task manager

编辑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/

相关文章:

c# - 无法在 WPF 项目中加载文件或程序集

python - 在python线程中关闭监听套接字

c# - 在 c# wpf 中,我可以将 listview 列动态构建为类方法吗?

ios - 制作线程化的 NSURLConnections

c++ - 如何为 parallel_invoke 设置进度条?

c# - ASP.NET 中的 XML POST 和解析

c# - 如何从字符串中删除表情符号字符?

c# - LastWriteTime 和 LastAccessTime 有什么区别

c# - LINQ 中更短的删除查询

c# - 如何在 xaml 中访问 Collection 中的基本数据上下文