1
1
using System ;
2
+ using System . Collections ;
3
+ using System . Collections . Concurrent ;
2
4
using System . Collections . Generic ;
5
+ using System . Linq ;
3
6
using System . Threading ;
7
+ using System . Threading . Tasks ;
4
8
5
9
namespace module . dawnlc . me
6
10
{
@@ -9,96 +13,151 @@ namespace module.dawnlc.me
9
13
/// </summary>
10
14
class ConsoleExpand : IDisposable
11
15
{
12
- private bool isDisposed = false ;
13
- private bool isDisposing = false ;
14
- private bool RenderCacheLock = false ;
15
- /// <summary>
16
- /// Console 高
17
- /// </summary>
18
- public static int High = Console . WindowHeight ;
19
- /// <summary>
20
- /// Console 宽
21
- /// </summary>
22
- public static int Width = Console . WindowWidth ;
23
-
24
- public static Thread RenderThread ;
25
-
26
- public static List < Content > RenderCache1 = new List < Content > ( ) ;
27
- public static List < Content > RenderCache2 = new List < Content > ( ) ;
28
-
29
- public class Content
16
+ public class Render : IDisposable
30
17
{
31
- public int Row { get ; set ; }
32
- public int Col { get ; set ; }
33
- public string ContentString { get ; set ; }
34
- public Content ( int row , int col , string content )
18
+ public class Content
35
19
{
36
- Row = row ;
37
- Col = col ;
38
- ContentString = content ;
39
- }
40
- }
41
-
42
- public ConsoleExpand ( )
43
- {
44
- Console . SetCursorPosition ( 0 , 0 ) ;
45
- Console . Clear ( ) ;
46
- RenderThread = new Thread ( OutputCanvas )
47
- {
48
- IsBackground = true
49
- } ;
50
- RenderThread . Start ( ) ;
51
- }
52
-
53
- public void OutputCanvas ( )
54
- {
55
- while ( ! isDisposing )
56
- {
57
- RenderCacheLock = true ;
58
- List < Content > Rendering = new List < Content > ( RenderCache1 ) ;
59
- foreach ( var item in Rendering )
20
+ public int Row { get ; set ; }
21
+ public int Col { get ; set ; }
22
+ public bool Cover { get ; set ; }
23
+ public string ContentString { get ; set ; }
24
+ public Content ( int row , int col , string content , bool cover = true )
60
25
{
61
- if ( item != null )
62
- {
63
- Console . SetCursorPosition ( 0 , item . Row ) ;
64
- Console . Write ( new string ( ' ' , Width ) ) ;
65
- Console . SetCursorPosition ( item . Col , item . Row ) ;
66
- Console . Write ( item . ContentString ) ;
67
- }
68
-
26
+ Row = row ;
27
+ Col = col ;
28
+ Cover = cover ;
29
+ ContentString = content ;
69
30
}
70
- Rendering . Clear ( ) ;
71
- RenderCache1 . Clear ( ) ;
31
+ }
32
+ public class RenderCache : ConcurrentQueue < Content >
33
+ {
34
+ public ConcurrentQueue < Content > Contents { get ; set ; }
35
+ public bool CacheLock { get ; set ; }
72
36
73
- RenderCache1 . AddRange ( RenderCache2 ) ;
74
- RenderCacheLock = false ;
37
+ public object SyncRoot => ( ( ICollection ) Contents ) . SyncRoot ;
75
38
76
- RenderCache2 . Clear ( ) ;
39
+ public bool IsSynchronized => ( ( ICollection ) Contents ) . IsSynchronized ;
77
40
78
- Thread . Sleep ( 32 ) ;
41
+ public RenderCache ( )
42
+ {
43
+ CacheLock = false ;
44
+ Contents = new ConcurrentQueue < Content > ( ) ;
45
+ }
46
+ public void Lock ( )
47
+ {
48
+ CacheLock = true ;
49
+ }
50
+ public void Unlock ( )
51
+ {
52
+ CacheLock = false ;
53
+ }
79
54
}
80
- }
81
-
82
- public void Print ( int Col , int Row , string Content )
83
- {
84
- try
55
+ private bool isDisposed = false ;
56
+ public int High = Console . WindowHeight ;
57
+ public int Width = Console . WindowWidth ;
58
+ public int Left = Console . CursorLeft ;
59
+ public int Top = Console . CursorTop ;
60
+ public Task RenderTask { get ; set ; }
61
+ public CancellationTokenSource RenderTaskTokenSource { get ; set ; }
62
+ public List < RenderCache > Pool { get ; set ; }
63
+ public int RenderInterval { get ; set ; }
64
+ public void Push ( Content content )
85
65
{
86
- if ( RenderCacheLock )
66
+ try
87
67
{
88
- RenderCache2 . Add ( new Content ( Row , Col , Content ) ) ;
68
+ Pool . Where ( p => ! p . CacheLock ) . First ( ) . Enqueue ( content ) ;
89
69
}
90
- else
70
+ catch ( Exception ex )
91
71
{
92
- RenderCache1 . Add ( new Content ( Row , Col , Content ) ) ;
72
+ throw new Exception ( "缺少可用的输出缓存区!" + ex . ToString ( ) ) ;
93
73
}
94
74
}
95
- catch ( Exception )
75
+ public Render ( int FPS = 10 , int PoolCount = 2 )
96
76
{
97
- //这里如果报错,肯定是破解速度过快.(跑完了7zip test并返回了结果只花了不到10毫秒)
98
- //不过不影响,漏显示一行不算什么大问题(笑
99
- //摸了
77
+ RenderInterval = 1000 / FPS ;
78
+ Pool = new List < RenderCache > ( ) ;
79
+ for ( int i = 0 ; i < PoolCount ; i ++ )
80
+ {
81
+ Pool . Add ( new RenderCache ( ) ) ;
82
+ }
83
+ RenderTaskTokenSource = new CancellationTokenSource ( ) ;
84
+ RenderTask = Task . Factory . StartNew ( ( ) => {
85
+ try
86
+ {
87
+ while ( true )
88
+ {
89
+ foreach ( var item in Pool . Where ( p => p . Count != 0 ) )
90
+ {
91
+ item . Lock ( ) ;
92
+ for ( int i = 0 ; i < item . Count ; i ++ )
93
+ {
94
+ if ( item . TryDequeue ( out Content content ) )
95
+ {
96
+ if ( content . Cover )
97
+ {
98
+ Console . SetCursorPosition ( 0 , content . Row ) ;
99
+ Console . Write ( new string ( ' ' , Width ) ) ;
100
+ }
101
+ Console . SetCursorPosition ( content . Col , content . Row ) ;
102
+ Console . Write ( content . ContentString ) ;
103
+ }
104
+ }
105
+ item . Unlock ( ) ;
106
+ }
107
+ RenderTaskTokenSource . Token . ThrowIfCancellationRequested ( ) ;
108
+ Thread . Sleep ( RenderInterval ) ;
109
+ }
110
+ }
111
+ catch ( OperationCanceledException )
112
+ {
113
+ //外部取消
114
+ return ;
115
+ }
116
+ catch ( Exception ex )
117
+ {
118
+ throw ex ;
119
+ }
120
+ } , RenderTaskTokenSource . Token ) ;
121
+ }
122
+ public void Close ( )
123
+ {
124
+ Dispose ( true ) ;
125
+ }
126
+ ~ Render ( )
127
+ {
128
+ Dispose ( false ) ;
129
+ }
130
+ void IDisposable . Dispose ( )
131
+ {
132
+ Dispose ( true ) ;
133
+ GC . SuppressFinalize ( this ) ;
134
+ }
135
+ protected virtual void Dispose ( bool disposing )
136
+ {
137
+ if ( ! isDisposed )
138
+ {
139
+ if ( disposing )
140
+ {
141
+ //释放
142
+ RenderTaskTokenSource . Cancel ( ) ;
143
+ RenderTask . Wait ( ) ;
144
+ Console . SetCursorPosition ( Left , Top ) ;
145
+ }
146
+ }
147
+ isDisposed = true ;
100
148
}
101
149
}
150
+
151
+ private bool isDisposed = false ;
152
+ private Render RenderTask { get ; set ; }
153
+ public ConsoleExpand ( )
154
+ {
155
+ RenderTask = new Render ( 25 ) ;
156
+ }
157
+ public void Print ( int row , int col , string content )
158
+ {
159
+ RenderTask . Push ( new Render . Content ( col , row , content ) ) ;
160
+ }
102
161
public void Close ( )
103
162
{
104
163
Dispose ( true ) ;
@@ -118,33 +177,12 @@ protected virtual void Dispose(bool disposing)
118
177
{
119
178
if ( disposing )
120
179
{
121
- RenderThread . Abort ( ) ;
122
- isDisposing = true ;
123
- foreach ( var item in RenderCache1 )
124
- {
125
- if ( item != null )
126
- {
127
- Console . SetCursorPosition ( 0 , item . Row ) ;
128
- Console . Write ( new string ( ' ' , Width ) ) ;
129
- Console . SetCursorPosition ( item . Col , item . Row ) ;
130
- Console . Write ( item . ContentString ) ;
131
- }
132
- }
133
- foreach ( var item in RenderCache2 )
134
- {
135
- if ( item != null )
136
- {
137
- Console . SetCursorPosition ( 0 , item . Row ) ;
138
- Console . Write ( new string ( ' ' , Width ) ) ;
139
- Console . SetCursorPosition ( item . Col , item . Row ) ;
140
- Console . Write ( item . ContentString ) ;
141
- }
142
- }
143
-
144
- isDisposing = false ;
180
+ //释放
181
+ RenderTask . Close ( ) ;
145
182
}
146
183
}
147
- isDisposed = true ; // 标识此对象已释放
184
+ isDisposed = true ;
148
185
}
186
+
149
187
}
150
188
}
0 commit comments