dotnet-campus / asyncworkercollection Goto Github PK
View Code? Open in Web Editor NEW高性能的多线程异步工具库。A collection of tools that support asynchronous methods and support high-performance multithreading.
License: MIT License
高性能的多线程异步工具库。A collection of tools that support asynchronous methods and support high-performance multithreading.
License: MIT License
如题,用Task.Wait的话又失去了async的意义
EventHandler
自定义无参委托FinishedEventHandler
internal delegate void FinishedEventHandler();
private event FinishedEventHandler? CurrentFinished;
_asyncQueue.CurrentFinished += CurrentFinished;
private void CurrentFinished()
{
_currentFinishedTaskCompletionSource.TrySetResult(true);
}
_asyncQueue.CurrentFinished -= CurrentFinished;
public void Dispose()
#region IDisposable Support
private bool disposedValue = false; // 要检测冗余调用
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// 释放托管状态(托管对象)。
lock (_asyncQueue)
{
_currentFinishedTaskCompletionSource.TrySetResult(true);
_asyncQueue.CurrentFinished -= CurrentFinished;
}
}
// TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。
// TODO: 将大型字段设置为 null。
disposedValue = true;
}
}
// TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。
// ~CurrentFinishedTask()
// {
// // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
// Dispose(false);
// }
// 添加此代码以正确实现可处置模式。
public void Dispose()
{
// 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
Dispose(true);
// TODO: 如果在以上内容中替代了终结器,则取消注释以下行。
// GC.SuppressFinalize(this);
}
#endregion
#region IDisposable Support
private bool disposedValue = false; // 要检测冗余调用
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// 释放托管状态(托管对象)。
ThrowIfDisposing();
_isDisposing = true;
// 当释放的时候,将通过 _queue 的 Clear 清空内容,而通过 _semaphoreSlim 的释放让 DequeueAsync 释放锁
// 此时将会在 DequeueAsync 进入 TryDequeue 方法,也许此时依然有开发者在 _queue.Clear() 之后插入元素,但是没关系,我只是需要保证调用 Dispose 之后会让 DequeueAsync 方法返回而已
_isDisposed = true;
_queue.Clear();
if (_dequeueAsyncEnterCount > 0)
{
// 释放 DequeueAsync 方法,释放次数为 DequeueAsync 在调用的次数
_semaphoreSlim.Release(_dequeueAsyncEnterCount);
}
_semaphoreSlim.Dispose();
}
// TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。
// TODO: 将大型字段设置为 null。
disposedValue = true;
}
}
// TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。
// ~AsyncQueue()
// {
// // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
// Dispose(false);
// }
// 添加此代码以正确实现可处置模式。
/// <summary>
/// 主要用来释放锁,让 DequeueAsync 方法返回,解决因为锁让此对象内存不释放
/// <para></para>
/// 这个方法不是线程安全
/// </summary>
public void Dispose()
{
// 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
Dispose(true);
// TODO: 如果在以上内容中替代了终结器,则取消注释以下行。
// GC.SuppressFinalize(this);
}
#endregion
当不断 InvokeAsync
而没时机执行的时候,会不停向 _queue
中增加元素而不释放。
现在库里面的 AsyncTaskQueue 是一个重量的方法,需要创建一个线程来做
期望还有提供使用线程池的方法
如果用户等待 AsyncAutoResetEvent 而没有做最终的释放,那么此时等待的代码将会内存泄露
如果有多个线程调用 ExecuteAsync 方法
如果 _executionResult 为空,那么都会进入 Lock 方法,而 lock 方法里面只是会让第第二个进入等待,也就是在第一个执行完成之后,依然会执行第二个线程
public class ExecuteOnceAwaiter<TResult>
{
/// <summary>
/// 表示只执行一次的任务
/// </summary>
/// <param name="asyncAction"></param>
public ExecuteOnceAwaiter(Func<Task<TResult>> asyncAction)
{
_asyncAction = asyncAction;
}
/// <summary>
/// 多次调用等待此方法只会执行一次
/// </summary>
/// <returns></returns>
public Task<TResult> ExecuteAsync()
{
if (_executionResult != null)
{
return _executionResult;
}
Lock(() => _executionResult = _asyncAction());
return _executionResult;
}
public void ResetWhileCompleted()
{
if (IsCompleted)
{
Lock(() => _executionResult = null);
}
}
private readonly Func<Task<TResult>> _asyncAction;
private Task<TResult> _executionResult;
private SpinLock _spinLock = new SpinLock(true);
private bool IsRunning => _executionResult?.IsCompleted is false;
private bool IsCompleted => _executionResult?.IsCompleted is true;
private void Lock(Action action)
{
var lockTaken = false;
try
{
_spinLock.Enter(ref lockTaken);
action();
}
finally
{
// 参数错误或锁递归时才会发生异常,所以此处几乎能肯定 lockTaken 为 true。
if (lockTaken) _spinLock.Exit();
}
}
}
在 https://github.com/dotnet-campus/dotnetCampus.Ipc 需要设置在结束的时候,无论 DoubleBufferTask 里面还有多少内容,还没使用的,全部清空
版本是最新版。
项目是一个blazor hybird wpf的混合项目,情况是大致这样的:
TaskMenuNumber
和 TodoMenuNumber
类都是task执行类,注册在依赖里,非SingleInstance
BaseAsyncQueue
是注册成了单例 获取字典中的 AsyncQueue,从而获取到Task。
我在A窗口初始化的时候创建了2个timer,timer里获取队列里的Task进行消费
出现的问题:
Task里有个大数据的计算每个分类的数量,这个会比较频繁,因为有task变动在别处就会push进入一个队列,让task在do方法里重新计算一下,结果发现只要是触发了Task内存会一直涨,没有释放,task里的do方法是没有返回和引用的,不知道为啥不会释放?
do 方法:
用dotMemory 工具查看dump文件发现都堆在了二代里,没有GC,具体都是堆在了异步方法里。
和walterlv老哥聊了一下,需要具体查看下啥原因。
由于对性能这方面不是特别熟悉,不知道是不是我用法的问题,理论上在do方法里哪怕用了linq 生成了数据的copy ,方法执行完 应该自动释放掉,哪怕不是立即释放 也会隔一段时间释放,测试是不断上涨,隔了一晚上也没释放,主动GC,也GC不下来。
[email protected]:microsoft/vs-threading.git
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.