需求分析:假定有3个线程,有一个PLC下位机,当连接成功时,开启3个线程干活,如果连接不成功,则重新开启3个线程。当3个线程开启成功并工作一段时间后 ,利用CancellationToken退出线程 。 设计如下 :首先设计一个类TaskModel,用来封装线程名字,任务,实际执行的委托及取消令牌,然后实例化三个TaskModel,并放入一个队列,最后开一个轮询线程,看看队列中的线程状态,如果没有running 就重新开启新的线程,主要利用Task的IsCanceled 、IsFaulted 和IsCompleted属性进行判断。
public class TaskModel
{
public string Name;
public Task Task;
public Action<CancellationToken> Action;
public CancellationTokenSource TokenSource;
public TaskModel(string name,Action<CancellationToken> action, CancellationTokenSource tokenSource)
{
this.Name = name;
this.Action = action;
this.TokenSource = tokenSource;
this.Task = Task.Run(() => action.Invoke(tokenSource.Token));
}
}
class Program
{
private static CancellationTokenSource cancel = new CancellationTokenSource();
private static ConcurrentQueue<TaskModel> tasks = new ConcurrentQueue<TaskModel>();
private static bool isConnect = false;
static void Main(string[] args)
{
TaskModel SleepTask = new TaskModel("Sleep线程", Sleep, cancel);
TaskModel WorkTask = new TaskModel("Work线程", Work, cancel);
TaskModel EatTask = new TaskModel("Eat线程", Eat, cancel);
tasks.Enqueue(SleepTask);
tasks.Enqueue(WorkTask);
tasks.Enqueue(EatTask);
Task.Run(() =>
{
Console.WriteLine($"Start...");
int i = 0;
while (i < 10)
{
foreach (var item in tasks)
{
if (item.Task.IsCanceled || item.Task.IsFaulted || item.Task.IsCompleted)
{
Console.WriteLine($"{DateTime.Now}: {item.Name} 重新启动!");
item.Task = Task.Run(() => item.Action.Invoke(item.TokenSource.Token));
}
Thread.Sleep(1000);
}
if (i++ == 0)
{
isConnect = true;
foreach (var item in tasks)
{
if (item.Task.Status == TaskStatus.RanToCompletion) continue;
item.Task.Start();
}
}
if (i == 5)
{
cancel.Cancel();
}
}
Console.WriteLine($"End...");
});
Console.ReadKey();
}
public static void Sleep(CancellationToken token)
{
while (isConnect && cancel.IsCancellationRequested == false)
{
Console.WriteLine($"{DateTime.Now}: Sleeping...");
Thread.Sleep(1000);
}
}
public static void Work(CancellationToken token)
{
while (isConnect && cancel.IsCancellationRequested == false)
{
Console.WriteLine($"{DateTime.Now}: Working...");
Thread.Sleep(1000);
}
}
public static void Eat(CancellationToken token)
{
while (isConnect && cancel.IsCancellationRequested == false)
{
Console.WriteLine($"{DateTime.Now}: Eatting...");
Thread.Sleep(1000);
}
}
}
|