!2459 新增: 线程执行运算时添加进度条

pull/2450/MERGE
张子涵 11 months ago committed by ChenX
parent 31449f394c
commit 9ba89592cc

@ -1,3 +1,4 @@
import { iaop } from "xaop";
import { Task } from "./Task";
/** 是否输出测试信息 */
@ -26,6 +27,16 @@ class WorkerPool
/** 线程ID */
private threadId = 0;
get Pool()
{
return this._Pool;
}
get TaskQueue()
{
return this._TaskQueue;
}
/** 添加任务 */
AppendTask(task: Task)
{
@ -47,6 +58,7 @@ class WorkerPool
else
{
this._TaskQueue.push(task);
this.AppendEvent(task);
this.Loop();
}
}
@ -65,7 +77,7 @@ class WorkerPool
thread.worker = undefined;
thread.workerCtor = undefined;
thread.task = undefined;
this.CloseEvent(task);
this.Loop();
}
}
@ -84,6 +96,7 @@ class WorkerPool
}
log(`设置【${thread.id}号线程】执行【任务${task.key}`);
this.UpdateEvent(task);
thread.worker.postMessage(thread.task.data);
// 返回结果
thread.worker.onmessage = e =>
@ -95,6 +108,7 @@ class WorkerPool
};
log(`${res.id}号线程】完成【任务${res.taskId}`, res.data);
thread.task = null;
this.StopEvent(task);
this.Loop();//先开启下一个任务 在进行主线程同步
task.then(res);
};
@ -123,9 +137,45 @@ class WorkerPool
{
const task = this._TaskQueue.shift();
this.UpdateTask(freeThread, task);
this.ExecuteEvent(task);
}
}
/** 添加任务的事件 */
@iaop
AppendEvent(task: Task)
{
log("添加任务");
}
/** 执行任务的事件 */
@iaop
ExecuteEvent(task: Task)
{
log("执行任务");
}
/** 更换任务的事件 */
@iaop
UpdateEvent(task: Task)
{
log("更换任务");
}
/** 结束任务的事件 */
@iaop
StopEvent(task: Task)
{
log("结束任务");
}
/** 关闭任务的事件 */
@iaop
CloseEvent(task: Pick<Task, "key" | "workerCtor">)
{
log("关闭任务");
}
/** 获取闲置线程 */
GetFreeThread(): Thread | undefined
{

@ -11,6 +11,7 @@ import CameraStateManage from '../UI/Components/CameraControlButton/CameraState/
import { CommandInputManage } from '../UI/Components/CommandInput/CommandInputManage';
import { MaskManage } from '../UI/Components/Modal/MaskManage';
import { ModalManage } from '../UI/Components/Modal/ModalsManage';
import TaskStateManage from '../UI/Components/TaskControl/TaskStateManage';
import { CommandStore, MsgInfo } from '../UI/Store/CommandStore';
import { ContextMenuServices } from './ContextMenu';
import { GetDistanceServices } from './GetDistanceServices';
@ -51,6 +52,7 @@ export class Editor
CommandInput: CommandInputManage;
SsgetServices: SsgetServiecs;
CameraState: CameraStateManage;
TaskState: TaskStateManage;
AxisMode: AxisModeManage;
KeywordsServices: GetKeyWordsServices;
@ -89,6 +91,7 @@ export class Editor
this.ModalManage = new ModalManage(this);
this.CommandInput = new CommandInputManage();
this.CameraState = new CameraStateManage();
this.TaskState = new TaskStateManage();
this.AxisMode = new AxisModeManage();
// new SpeechBoxManage();

@ -0,0 +1,96 @@
.TaskState {
position: absolute;
bottom: 60px;
right: 10px;
}
.task_process {
border-radius: 5px;
box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
overflow: hidden;
font-size: 14px;
cursor: default;
.gap {
width: 10px;
height: 10px;
}
.color_red {
color: #f00;
font-weight: bold;
}
.color_green {
color: #0c5;
font-weight: bold;
}
.abstract {
display: flex;
justify-content: space-between;
align-items: center;
width: 400px;
height: 50px;
background: #456;
color: #eee;
.info {
display: flex;
padding: 5px 10px;
}
.expand {
display: flex;
justify-content: center;
align-items: center;
padding: 0 20px;
height: 50px;
cursor: pointer;
}
.expand:hover {
color: #ccc;
}
}
.description {
overflow-y: auto;
width: 400px;
max-height: 300px;
background: #eee;
color: #333;
.task {
display: flex;
justify-content: space-between;
align-items: center;
padding: 5px 10px;
background: #dfe;
border-bottom: 1px solid #5b5;
.operate {
display: flex;
justify-content: space-between;
align-items: center;
.stop {
cursor: pointer;
padding: 2px 5px;
background: #d44;
color: #fff;
border-radius: 5px;
}
.stop:hover {
background: #f55;
}
}
}
.queue {
background: #fed;
border-color: #f55;
}
}
}

@ -0,0 +1,101 @@
import { observer } from 'mobx-react';
import React, { Component, useState } from 'react';
import { app } from '../../../ApplicationServices/Application';
import { WORKER_POOL } from '../../../Common/ThreadPool/WorkerPool';
import { Board } from '../../../DatabaseServices/Entity/Board';
import './TaskState.less';
import TaskStore, { TaskItem } from './TaskStore';
/** 任务状态监视器 */
@observer
export default class TaskState extends Component
{
taskStore = TaskStore.GetInstance();
/** 定位到板材 */
ToBorad = (e: TaskItem) =>
{
app.Editor.SetSelection([e.id.key] as Board[]);
app.Viewer.ZoomtoEntitys([e.id.key] as Board[]);
};
/** 停止任务 */
StopTask = (e: TaskItem) =>
{
// 1.拿到线程池中的任务列表
const taskList = WORKER_POOL.Pool.filter(e => !!e.task).map(e => e.task);
// 2.停止对应的任务
const task = taskList.find(task => e.id.key === task.key && e.id.workerCtor === task.workerCtor);
if (task)
{
WORKER_POOL.TerminateTask(task);
this.taskStore.GetTaskList();
}
};
render()
{
return (
<div className='TaskState' style={{ display: this.taskStore.isClose ? "none" : "block" }}>
<TaskProcess pool={this.taskStore.workerList} queue={this.taskStore.taskList} ClickName={this.ToBorad} ClickStop={this.StopTask} />
</div>
);
}
}
/** 监视器样式 */
function TaskProcess({ pool, queue, ClickName, ClickStop }: { pool: TaskItem[], queue: TaskItem[]; ClickName: Function; ClickStop: Function; })
{
const [isExpend, setIsExpend] = useState(false);
/** 是否展开详情 */
const HandleExpend = () =>
{
setIsExpend(!isExpend);
};
return (<div className="task_process">
<div className="abstract">
<div className="info">
<div><span className="color_green"> {pool.length} </span></div>
<div className="gap"></div>
<div><span className="color_red"> {queue.length} </span></div>
</div>
<div className="expand" onClick={HandleExpend}>
<div>{isExpend ? "收起" : "展开"}</div>
</div>
</div>
<div className="description" style={{ display: isExpend ? "block" : "none" }}>
{
pool.map(e => <TaskInPool task={e} ClickName={ClickName} ClickStop={ClickStop} />)
}
{
queue.map(e => <TaskInQueue task={e} ClickName={ClickName} />)
}
</div>
</div>);
}
/** 正在执行的任务 */
function TaskInPool({ task, ClickName, ClickStop }: { task: TaskItem; ClickName: Function; ClickStop: Function; })
{
/** 超过30秒显示红色 */
const timeout = 30;
return <div className="task">
<div className="broad" onClick={() => ClickName(task)}>{task.name}</div>
<div className="operate">
<div className="time"><span className={task.time > timeout ? "color_red" : "color_green"}> {task.time} </span></div>
<div className="gap"></div>
<div className="stop" onClick={() => ClickStop(task)}></div>
</div>
</div>;
}
/** 等待执行的任务 */
function TaskInQueue({ task, ClickName }: { task: TaskItem; ClickName: Function; })
{
return <div className="task queue">
<div className="broad" onClick={() => ClickName(task)}>{task.name}</div>
</div>;
}

@ -0,0 +1,19 @@
import React from 'react';
import ReactDOM from 'react-dom';
import TaskState from './TaskState';
export default class TaskStateManage
{
private _TaskStateContainer: HTMLElement;
constructor()
{
this._TaskStateContainer = document.createElement('div');
this._TaskStateContainer.id = 'TaskState';
document.getElementById('Webgl').appendChild(this._TaskStateContainer);
}
RenderTaskState()
{
ReactDOM.render(<TaskState />, this._TaskStateContainer);
}
}

@ -0,0 +1,128 @@
import { observable } from "mobx";
import { end } from "xaop";
import { Task } from "../../../Common/ThreadPool/Task";
import { WORKER_POOL } from "../../../Common/ThreadPool/WorkerPool";
export interface TaskItem
{
id: any;
name: string;
time: number;
}
export default class TaskStore
{
/** 正在执行的列表 */
@observable workerList = [] as TaskItem[];
/** 剩余任务的列表 */
@observable taskList = [] as TaskItem[];
/** 定时器 */
timed;
/** 是否关闭 */
isClose = true;
/** 更新运行时间 */
UpdateTime = () =>
{
if (this.timed) clearInterval(this.timed);
if (this.isClose) return;
this.timed = setInterval(() =>
{
this.workerList = this.workerList.map(e =>
{
return {
...e,
time: ++e.time
};
});
}, 1000);
};
/** 获取任务列表 */
GetTaskList = (task?: Task) =>
{
// 1.拿到线程池中的任务列表
const taskList = WORKER_POOL.Pool.filter(e => !!e.task).map(e => e.task);
// 2.映射成监视器所需的数据
const workerList = taskList.map(task =>
{
const item = this.workerList.find(e => e.id.key === task.key && e.id.workerCtor === task.workerCtor);
return {
id: {
key: task.key,
workerCtor: task.workerCtor,
},
name: task.key.Name as string,
// 同步运行时间
time: item ? item.time : 0,
};
});
this.workerList = workerList;
// 更换任务时,重置时间
if (task)
{
const item = this.workerList.find(e => e.id.key === task.key && e.id.workerCtor === task.workerCtor);
if (item) item.time = 0;
}
// 剩余任务
const taskQueue = WORKER_POOL.TaskQueue.map(task =>
{
return {
id: {
key: task.key,
workerCtor: task.workerCtor,
},
name: task.key.Name as string,
time: 0,
};
});
this.taskList = taskQueue;
// 开始计时
this.UpdateTime();
// 没任务了,倒计时关闭
if (this.workerList.length === 0 && this.taskList.length === 0)
{
setTimeout(() =>
{
if (this.workerList.length === 0 && this.taskList.length === 0)
this.isClose = true;
}, 1000);
}
else this.isClose = false;
};
private static _SingleInstance: TaskStore;
static GetInstance(): TaskStore
{
if (this._SingleInstance) return this._SingleInstance;
this._SingleInstance = new TaskStore();
return this._SingleInstance;
}
}
// 注入
end(WORKER_POOL.AppendEvent, (task: Task) =>
{
const taskStore = TaskStore.GetInstance();
taskStore.GetTaskList();
});
end(WORKER_POOL.ExecuteEvent, (task: Task) =>
{
const taskStore = TaskStore.GetInstance();
taskStore.GetTaskList();
});
end(WORKER_POOL.UpdateEvent, (task: Task) =>
{
const taskStore = TaskStore.GetInstance();
taskStore.GetTaskList(task);
});
end(WORKER_POOL.StopEvent, (task: Task) =>
{
const taskStore = TaskStore.GetInstance();
taskStore.GetTaskList();
});
end(WORKER_POOL.CloseEvent, (task: Pick<Task, "key" | "workerCtor">) =>
{
const taskStore = TaskStore.GetInstance();
taskStore.GetTaskList();
});

@ -63,6 +63,7 @@ export class WebCAD
this.renderCommandInput();
this.renderCameraState();
this.renderAxisMode();
this.renderTaskState();
appUi = this;
@ -280,6 +281,10 @@ export class WebCAD
{
app.Editor.CameraState.RenderCameraState();
}
renderTaskState()
{
app.Editor.TaskState.RenderTaskState();
}
renderAxisMode()
{
app.Editor.AxisMode.RenderCameraState();

Loading…
Cancel
Save