如何检查线程是否完整?

时间:2016-06-16 20:28:13

标签: c# multithreading

我遇到很多麻烦。考虑这个例子:

public class Test {
    Thread t;

    public Test() {
        t = new Thread(ThreadFunction);
    }

    public void Start() {
        t.Start();
    }

    private void ThreadFunction() {
        Thread.Sleep(5000);
        Console.WriteLine("Function Complete");
    }    
}


public static class Main {
    public Main() {
        Test test = new Test();
        test.Start();

        // sleep longer than my worker so it finishes
        Thread.Sleep(10000);

        // a place to place a breakpoint
        bool breakPointHere = true;
    }        
}

现在,我看到了console.log的输出,但是当我检查Test的线程对象时,我看到IsAlive仍然是真的,而ThreadStatus = TheadStatus.Running。为什么是这样?我希望检测到该线程是真正完整的,但是我很困惑如果ThreadFunction()完​​成它仍然可以被认为是运行的吗?

编辑2:

我终于找到了原因,更新了代码,我将回答我自己的问题

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;


namespace ConsoleApplication1 {
    public abstract class Worker {
        protected bool shutdown;
        protected Thread t;

        private bool _isStopped = true;
        public bool IsStopped {
            get {
                return t.ThreadState == ThreadState.Stopped;
            }
        }

        private bool _isPaused = false;
        public bool IsPaused {
            get {
                return _isPaused;
            }
        }

        private string stringRepresentation;

        public Worker() {
            t = new Thread(ThreadFunction);
            stringRepresentation = "Thread id:" + t.ManagedThreadId;
            t.Name = stringRepresentation;
        }


        public void Start() {
            OnBeforeThreadStart();
            t.Start();
        }

        public void ScheduleStop() {
            shutdown = true;
        }

        public void SchedulePause() {
            OnPauseRequest();
            _isPaused = true;
        }

        public void Unpause() {
            _isPaused = false;
        }

        public void ForceStop() {
            t.Abort();
        }


        /// <summary>
        /// The main thread loop.
        /// </summary>
        private void ThreadFunction() {
            OnThreadStart();
            while (!shutdown) {
                if (!IsPaused) {
                    if (!OnLoop()) {
                        break;
                    }
                }
                Thread.Sleep(1000);
            }
            OnShutdown();
        }

        public abstract void OnBeforeThreadStart();
        public abstract void OnThreadStart();
        public abstract bool OnLoop();
        public abstract void OnShutdown();
        public abstract void OnPauseRequest();


        public override string ToString() {
            return stringRepresentation;
        }
    }


    public class Test : Worker {
        public override void OnBeforeThreadStart() {
            Log.WriteLine(this + ": Thread about to be started...");
        }

        public override void OnThreadStart() {
            Log.WriteLine(this + ": Thread Started!");
        }

        public override bool OnLoop() {
            Log.WriteLine(this + ": I am doing the things...");
            return true;
        }

        public override void OnShutdown() {
            Log.WriteLine(this + ": Shutting down!");
        }

        public override void OnPauseRequest() {            
        }
    }



public static class Log {
    public delegate void LogDelegate(string text, string eventTime, Severity severity);

    public static event LogDelegate OnWriteLine;

    private static Queue<string> _pendingFileWrites = new Queue<string>();


    public enum Severity {
        Info,
        Warning,
        Error
    }


    public static void WriteLine(object line, Severity severity = Severity.Info) {
        string eventTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        string formatted = "[" + eventTime + "]: " + line;
        Console.WriteLine(formatted);

        lock (_pendingFileWrites) {
            _pendingFileWrites.Enqueue(formatted);
        }

        if (OnWriteLine != null) {
            // this is the offending line:
            OnWriteLine.Invoke((string)line, eventTime, severity);
        }
    }


    public static void WriteToFile(string path) {
        lock(_pendingFileWrites) {
            StreamWriter sw = File.AppendText(path);        
            while(_pendingFileWrites.Count > 0) {
                sw.WriteLine(
                    _pendingFileWrites.Dequeue()
                );
            }
            sw.Close();
        }   
    }
}



    class Program {
        static void Main(string[] args) {
            List<Test> tests = new List<Test>();
            for(int i = 0; i < 10; i++) {
                Test test = new Test();
                test.Start();
                tests.Add(test);
            }

            // sleep a little bit so they do the things
            Thread.Sleep(10000);

            foreach (Test test in tests) {
                test.ScheduleStop();
            }

            bool allStopped;
            do {
                allStopped = true;
                foreach (Test test in tests) {
                    if (!test.IsStopped) {
                        allStopped = false;
                        break;
                    }
                }
            } while (!allStopped);

            Console.WriteLine("Done!");

            // a place to place a breakpoint
            bool breakPointHere = true;
        }
    }
}

3 个答案:

答案 0 :(得分:2)

我认为你的原始测试会让你相信.IsAlive会有一些缺陷,我在你的问题中调整你的程序以使其编译并能够看到它是哪个线程创建

public class Program
{
    public class Test
    {
        Thread t;

        public Test()
        {
            t = new Thread(ThreadFunction);
            t.Name = "TestThread";
        }

        public void Start()
        {
            t.Start();
        }

        private void ThreadFunction()
        {
            Thread.Sleep(5000);
            Console.WriteLine("Function Complete");
        }
    }


    public static void Main()
    {
        Test test = new Test();
        test.Start();

        // sleep longer than my worker so it finishes
        Thread.Sleep(10000);

        // a place to place a breakpoint
        bool breakPointHere = true;
    }
}

这是ThreadFunction内部运行线程的屏幕截图

enter image description here

这是程序结尾的截图

enter image description here

请注意,没有“TestThread”线程。

以下是本地窗口的截图

enter image description here

IsAlive是假的。

答案 1 :(得分:1)

你真的需要睡觉等待你的线程完成吗? 如果你不这样做,一个更好,更强大的解决方案就是使用Thread.Join()

public static class Main {
    public Main() {
        Test test = new Test();
        test.Start();

        test.Join(); // Waits for test to complete
        bool breakPointHere = true;
    }        
}

答案 2 :(得分:0)

事实证明我的问题是我的日志记录方法正在调用UI线程函数,如下所示:

https://$user:$apiKey@api.softlayer.com/rest/v3/SoftLayer_Product_Order/placeOrder

Method: Post

{  
   "parameters":[  
      {  
         "complexType":"SoftLayer_Container_Product_Order_Dns_Domain_Registration",
         "quantity":1,
         "packageId":0,
         "administrativeContact":{  
            "address1":"address test",
            "city":"cityTest",
            "country":"BO",
            "email":"noreply@softlayer.com",
            "firstName":"Jhon",
            "lastName":"Travolta",
            "organizationName":"Company Name",
            "phone":"7074485559",
            "postalCode":"0591",
            "state":"OT",
            "type":"admin"
         },
         "billingContact":{  
            "address1":"address test",
            "city":"cityTest",
            "country":"BO",
            "email":"noreply@softlayer.com",
            "firstName":"Jhon",
            "lastName":"Travolta",
            "organizationName":"Company Name",
            "phone":"7074485559",
            "postalCode":"0591",
            "state":"OT",
            "type":"billing"
         },
         "ownerContact":{  
            "address1":"address test",
            "city":"cityTest",
            "country":"BO",
            "email":"noreply@softlayer.com",
            "firstName":"Jhon",
            "lastName":"Travolta",
            "organizationName":"Company Name",
            "phone":"7074485559",
            "postalCode":"0591",
            "state":"OT",
            "type":"owner"
         },
         "technicalContact":{  
            "address1":"address test",
            "city":"cityTest",
            "country":"BO",
            "email":"noreply@softlayer.com",
            "firstName":"Jhon",
            "lastName":"Travolta",
            "organizationName":"Company Name",
            "phone":"7074485559",
            "postalCode":"0591",
            "state":"OT",
            "type":"tech"
         },
         "domainRegistrationList":[  
            {  
               "domainName":"testrcv.com",
               "registrationPeriod":1
            }
         ],
         "registrationType":"new"
      }
   ]
}

在Invoke()行,线程将永远挂起。解决方案是用BeginInvoke()替换它。

编辑:另外,我的例子是/很差。我以为我没有从根本上理解线程,而且我的例子已经足够了。希望有人搜索这个并且有同样的原因,并且可以尝试这个解决方案。