C# 如何检查线程是否完整?
我在这方面遇到了很多麻烦。考虑这个例子:C# 如何检查线程是否完整?,c#,multithreading,C#,Multithreading,我在这方面遇到了很多麻烦。考虑这个例子: public class Test { Thread t; public Test() { t = new Thread(ThreadFunction); } public void Start() { t.Start(); } private void ThreadFunction() { Thread.Sleep(5000); Con
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的输出,但当我检查测试的thread对象时,我看到IsAlive仍然为true,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;
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用系统线程;
使用System.Threading.Tasks;
命名空间控制台应用程序1{
公共抽象类工作者{
保护性停机;
保护螺纹t;
private bool_isStopped=true;
公共图书馆{
得到{
返回t.ThreadState==ThreadState.Stopped;
}
}
私有bool_isPaused=false;
公共场所{
得到{
返回(i);;
}
}
私有字符串表示;
公职人员(){
t=新螺纹(螺纹功能);
stringRepresentation=“线程id:+t.ManagedThreadId;
t、 名称=字符串表示;
}
公开作废开始(){
OnBeforeThreadStart();
t、 Start();
}
public void ScheduleStop(){
关机=真;
}
公共无效计划暂停(){
OnPauseRequest();
_isPaused=真;
}
公共无效取消暂停(){
_isPaused=false;
}
公共停车场{
t、 中止();
}
///
///主线程循环。
///
私有函数(){
OnThreadStart();
而(!关机){
如果(!i暂停){
如果(!OnLoop()){
打破
}
}
睡眠(1000);
}
OnShutdown();
}
公共摘要void OnBeforeThreadStart();
公共摘要在readstart()上无效;
公共抽象bool OnLoop();
公共摘要void OnShutdown();
公共摘要void OnPauseRequest();
公共重写字符串ToString(){
返回表示;
}
}
公开班级考试:工人{
public override void OnBeforeThreadStart(){
WriteLine(此+“:即将启动的线程…”);
}
public override void OnThreadStart(){
Log.WriteLine(此+“:线程已启动!”);
}
公共覆盖bool OnLoop(){
Log.WriteLine(这个+“:我正在做这些事情…”);
返回true;
}
公共覆盖无效OnShutdown(){
Log.WriteLine(此+“:正在关闭!”);
}
公共覆盖无效OnPauseRequest(){
}
}
公共静态类日志{
公共委托void LogDelegate(字符串文本、字符串事件时间、严重性);
公共静态事件日志委托OnWriteLine;
私有静态队列_pendingFileWrites=新队列();
公共枚举严重性{
信息,
警告
错误
}
公共静态无效写入线(对象行,严重性=严重性.Info){
字符串eventTime=DateTime.Now.ToString(“yyyy-MM-dd HH:MM:ss”);
字符串格式为=“[”+事件时间+”]:“+行;
Console.WriteLine(格式化);
锁定(_pendingFileWrites){
_pendingFileWrites.Enqueue(格式化);
}
if(OnWriteLine!=null){
//这是一条令人不快的线:
调用((字符串)行、事件时间、严重性);
}
}
公共静态void WriteToFile(字符串路径){
锁定(_pendingFileWrites){
StreamWriter sw=File.AppendText(路径);
而(_pendingFileWrites.Count>0){
sw.WriteLine(
_pendingFileWrites.Dequeue()
);
}
sw.Close();
}
}
}
班级计划{
静态void Main(字符串[]参数){
列表测试=新列表();
对于(int i=0;i<10;i++){
测试=新测试();
test.Start();
测试。添加(测试);
}
//睡一点,这样他们就能做事情了
睡眠(10000);
foreach(测试中的测试){
test.ScheduleStop();
}
布尔停了下来;
做{
allStopped=true;
foreach(测试中的测试){
如果(!test.IsStopped){
allStopped=false;
打破
}
}
}而(!全部停止);
控制台。WriteLine(“完成!”);
//放置断点的位置
bool=true;
}
}
}
您真的需要睡眠来等待线程完成吗?
如果您不这样做,一个更好、更健壮的解决方案将是使用
你真的需要睡觉来等待线程完成吗? 如果您不这样做,一个更好、更健壮的解决方案将是使用
我认为你最初的测试让你相信
.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内部运行线程的屏幕截图
这是节目结尾的截图
请注意,没有“TestThread”线程
这是本地人窗口的屏幕截图
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;
}
}
private void LogToForm(object line, string eventTime, Log.Severity severity) {
if (dataGridView_LogInfo.InvokeRequired) {
dataGridView_LogInfo.Invoke (
new Action<object, string, Log.Severity>(LogtoFormCallback),
new object[] { line, eventTime, severity }
);
} else {
LogtoFormCallback(line, eventTime, severity);
}
}