Skip to content

Commit bb34116

Browse files
izanhzhArgoZhang
andauthored
feat(MiniExcelDataReaderBase): add asynchronous support (#706)
* feat(MiniExcelDataReaderBase): Add asynchronous support * fix `ReadAsync` bug * remove the error submission code * add unit test * optimization cancellation * optimization disposeAsync * optimized code * chore: bump version 1.36.1 * refactor: 格式化代码 --------- Co-Authored-By: Argo Zhang <argo@live.ca>
1 parent 74477f1 commit bb34116

File tree

9 files changed

+383
-21
lines changed

9 files changed

+383
-21
lines changed

src/MiniExcel/Csv/CsvWriter.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,8 @@ public void Insert()
140140
await Task.Run(() => SaveAs(), cancellationToken).ConfigureAwait(false);
141141
}
142142

143-
private void GenerateSheetByIDataReader(object value, string seperator, string newLine, StreamWriter writer)
143+
private void GenerateSheetByIDataReader(IDataReader reader, string seperator, string newLine, StreamWriter writer)
144144
{
145-
var reader = (IDataReader)value;
146-
147145
int fieldCount = reader.FieldCount;
148146
if (fieldCount == 0)
149147
throw new InvalidDataException("fieldCount is 0");
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System;
2+
using System.Data;
3+
using System.Threading;
4+
using System.Threading.Tasks;
5+
6+
namespace MiniExcelLibs
7+
{
8+
#if !NET8_0_OR_GREATER
9+
public interface IMiniExcelDataReader : IDataReader
10+
#else
11+
public interface IMiniExcelDataReader : IDataReader, IAsyncDisposable
12+
#endif
13+
{
14+
Task CloseAsync();
15+
16+
Task<string> GetNameAsync(int i, CancellationToken cancellationToken = default);
17+
18+
Task<object> GetValueAsync(int i, CancellationToken cancellationToken = default);
19+
20+
Task<bool> NextResultAsync(CancellationToken cancellationToken = default);
21+
22+
Task<bool> ReadAsync(CancellationToken cancellationToken = default);
23+
}
24+
}

src/MiniExcel/MiniExcelDataReader.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public override string GetName(int i)
6565
{
6666
return _keys[i];
6767
}
68+
6869
/// <inheritdoc/>
6970
protected override void Dispose(bool disposing)
7071
{

src/MiniExcel/MiniExcelDataReaderBase.cs

Lines changed: 138 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
{
33
using System;
44
using System.Data;
5+
using System.Threading;
6+
using System.Threading.Tasks;
57

68
/// <summary>
7-
/// IDataReader Base Class
9+
/// IMiniExcelDataReader Base Class
810
/// </summary>
9-
public abstract class MiniExcelDataReaderBase : IDataReader
11+
public abstract class MiniExcelDataReaderBase : IMiniExcelDataReader
1012
{
1113
/// <summary>
1214
/// <inheritdoc/>
@@ -202,26 +204,124 @@ public abstract class MiniExcelDataReaderBase : IDataReader
202204
/// <returns></returns>
203205
public virtual bool NextResult() => false;
204206

207+
/// <summary>
208+
/// <inheritdoc/>
209+
/// </summary>
210+
/// <param name="cancellationToken"></param>
211+
/// <returns></returns>
212+
public virtual Task<bool> NextResultAsync(CancellationToken cancellationToken = default)
213+
{
214+
if (cancellationToken.IsCancellationRequested)
215+
{
216+
return MiniExcelTask.FromCanceled<bool>(cancellationToken);
217+
}
218+
else
219+
{
220+
try
221+
{
222+
return NextResult() ? Task.FromResult(true) : Task.FromResult(false);
223+
}
224+
catch (Exception e)
225+
{
226+
return MiniExcelTask.FromException<bool>(e);
227+
}
228+
}
229+
}
230+
205231
/// <summary>
206232
/// <inheritdoc/>
207233
/// </summary>
208234
/// <param name="i"></param>
209235
/// <returns></returns>
210236
public abstract string GetName(int i);
211237

238+
/// <summary>
239+
/// <inheritdoc/>
240+
/// </summary>
241+
/// <param name="i"></param>
242+
/// <param name="cancellationToken"></param>
243+
/// <returns></returns>
244+
public virtual Task<string> GetNameAsync(int i, CancellationToken cancellationToken = default)
245+
{
246+
if (cancellationToken.IsCancellationRequested)
247+
{
248+
return MiniExcelTask.FromCanceled<string>(cancellationToken);
249+
}
250+
else
251+
{
252+
try
253+
{
254+
return Task.FromResult(GetName(i));
255+
}
256+
catch (Exception e)
257+
{
258+
return MiniExcelTask.FromException<string>(e);
259+
}
260+
}
261+
}
262+
212263
/// <summary>
213264
/// <inheritdoc/>
214265
/// </summary>
215266
/// <param name="i"></param>
216267
/// <returns></returns>
217268
public abstract object GetValue(int i);
218269

270+
/// <summary>
271+
/// <inheritdoc/>
272+
/// </summary>
273+
/// <param name="i"></param>
274+
/// <param name="cancellationToken"></param>
275+
/// <returns></returns>
276+
public virtual Task<object> GetValueAsync(int i, CancellationToken cancellationToken = default)
277+
{
278+
if (cancellationToken.IsCancellationRequested)
279+
{
280+
return MiniExcelTask.FromCanceled<object>(cancellationToken);
281+
}
282+
else
283+
{
284+
try
285+
{
286+
return Task.FromResult(GetValue(i));
287+
}
288+
catch (Exception e)
289+
{
290+
return MiniExcelTask.FromException<object>(e);
291+
}
292+
}
293+
}
294+
219295
/// <summary>
220296
/// <inheritdoc/>
221297
/// </summary>
222298
/// <returns></returns>
223299
public abstract bool Read();
224300

301+
/// <summary>
302+
/// <inheritdoc/>
303+
/// </summary>
304+
/// <param name="cancellationToken"></param>
305+
/// <returns></returns>
306+
public virtual Task<bool> ReadAsync(CancellationToken cancellationToken = default)
307+
{
308+
if (cancellationToken.IsCancellationRequested)
309+
{
310+
return MiniExcelTask.FromCanceled<bool>(cancellationToken);
311+
}
312+
else
313+
{
314+
try
315+
{
316+
return Read() ? Task.FromResult(true) : Task.FromResult(false);
317+
}
318+
catch (Exception e)
319+
{
320+
return MiniExcelTask.FromException<bool>(e);
321+
}
322+
}
323+
}
324+
225325
/// <summary>
226326
/// <inheritdoc/>
227327
/// </summary>
@@ -233,10 +333,18 @@ public virtual void Close()
233333
/// <summary>
234334
/// <inheritdoc/>
235335
/// </summary>
236-
/// <param name="disposing"></param>
237-
protected virtual void Dispose(bool disposing)
336+
/// <returns></returns>
337+
public virtual Task CloseAsync()
238338
{
239-
339+
try
340+
{
341+
Close();
342+
return MiniExcelTask.CompletedTask;
343+
}
344+
catch (Exception e)
345+
{
346+
return MiniExcelTask.FromException(e);
347+
}
240348
}
241349

242350
/// <summary>
@@ -247,5 +355,30 @@ public void Dispose()
247355
Dispose(true);
248356
GC.SuppressFinalize(this);
249357
}
358+
359+
#if NET8_0_OR_GREATER
360+
/// <summary>
361+
/// <inheritdoc/>
362+
/// </summary>
363+
/// <returns></returns>
364+
/// <exception cref="NotImplementedException"></exception>
365+
public virtual ValueTask DisposeAsync()
366+
{
367+
Dispose();
368+
return default;
369+
}
370+
#endif
371+
372+
/// <summary>
373+
/// <inheritdoc/>
374+
/// </summary>
375+
/// <param name="disposing"></param>
376+
protected virtual void Dispose(bool disposing)
377+
{
378+
if (disposing)
379+
{
380+
Close();
381+
}
382+
}
250383
}
251384
}

src/MiniExcel/MiniExcelLibs.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<TargetFrameworks>net45;netstandard2.0;net8.0;</TargetFrameworks>
4-
<Version>1.36.0</Version>
4+
<Version>1.36.1</Version>
55
</PropertyGroup>
66
<PropertyGroup>
77
<AssemblyName>MiniExcel</AssemblyName>

src/MiniExcel/MiniExcelTask.cs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using System;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
5+
namespace MiniExcelLibs
6+
{
7+
internal class MiniExcelTask
8+
{
9+
#if NET45
10+
public static Task CompletedTask = Task.FromResult(0);
11+
#else
12+
public static Task CompletedTask = Task.CompletedTask;
13+
#endif
14+
15+
public static Task FromException(Exception exception)
16+
{
17+
#if NET45
18+
var tcs = new TaskCompletionSource<object>();
19+
tcs.SetException(exception);
20+
return tcs.Task;
21+
#else
22+
return Task.FromException(exception);
23+
#endif
24+
}
25+
26+
public static Task<T> FromException<T>(Exception exception)
27+
{
28+
#if NET45
29+
var tcs = new TaskCompletionSource<T>();
30+
tcs.SetException(exception);
31+
return tcs.Task;
32+
#else
33+
return Task.FromException<T>(exception);
34+
#endif
35+
}
36+
37+
public static Task FromCanceled(CancellationToken cancellationToken)
38+
{
39+
#if NET45
40+
var tcs = new TaskCompletionSource<object>();
41+
cancellationToken.Register(() => tcs.SetCanceled());
42+
return tcs.Task;
43+
#else
44+
return Task.FromCanceled(cancellationToken);
45+
#endif
46+
}
47+
48+
public static Task<T> FromCanceled<T>(CancellationToken cancellationToken)
49+
{
50+
#if NET45
51+
var tcs = new TaskCompletionSource<T>();
52+
cancellationToken.Register(() => tcs.SetCanceled());
53+
return tcs.Task;
54+
#else
55+
return Task.FromCanceled<T>(cancellationToken);
56+
#endif
57+
}
58+
}
59+
}

0 commit comments

Comments
 (0)