У меня с этим много проблем. Рассмотрим следующий пример:Как проверить, что поток завершен?
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() завершает?
EDIT 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;
}
}
}
Вы уверены, что искали подходящую тему? Сделайте 't.Name =" TestThread ";' перед тем, как вы сделаете 't.Start()', чтобы помочь вам однозначно идентифицировать поток. Кроме того, не так часто работать непосредственно с классом «Thread» в современном C#, в современном C# вы обычно работаете с абстракцией 'Task', которая ее обертывает. Наконец, где вы получаете 'Console.Log (' from, метод 'Log' не является частью встроенного класса' System.Console'. –
Это очень урезанный пример, но в моем реальном мире позаботьтесь только об этой теме (в дополнение к основной теме), поэтому я точно знаю, что это правильный поток, на который я смотрю. Однако я не знал об абстракции задачи. Я проверю это, но я все еще хочу понять это лучше. – dmarra
Также Console.Log doens; t существует. Я смешал мой .Net и Unity C#, когда я выкачал этот пример: P. Это Console.WriteLine() – dmarra