Giter Site home page Giter Site logo

dotnet-campus / asyncworkercollection Goto Github PK

View Code? Open in Web Editor NEW
176.0 176.0 43.0 176 KB

高性能的多线程异步工具库。A collection of tools that support asynchronous methods and support high-performance multithreading.

License: MIT License

C# 100.00%
dotnet dotnet-core

asyncworkercollection's People

Contributors

github-actions[bot] avatar h82258652 avatar handsome08 avatar kkwpsv avatar lindexi avatar walterlv avatar xinyuehtx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

asyncworkercollection's Issues

对AsyncQueue优化

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

ExecuteOnceAwaiter 非线程安全

如果有多个线程调用 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();
            }
        }
    }

Task里执行大数据计算内存没有正常释放的情况

版本是最新版。

项目是一个blazor hybird wpf的混合项目,情况是大致这样的:

TaskMenuNumber TodoMenuNumber 类都是task执行类,注册在依赖里,非SingleInstance
image

BaseAsyncQueue是注册成了单例 获取字典中的 AsyncQueue,从而获取到Task。

image

我在A窗口初始化的时候创建了2个timer,timer里获取队列里的Task进行消费

image

出现的问题:
Task里有个大数据的计算每个分类的数量,这个会比较频繁,因为有task变动在别处就会push进入一个队列,让task在do方法里重新计算一下,结果发现只要是触发了Task内存会一直涨,没有释放,task里的do方法是没有返回和引用的,不知道为啥不会释放?

do 方法:

)4)P4V)@}~6Z9B7X2NL%V0K
M}NZSF1XVC N8S@%ZH)X`45

用dotMemory 工具查看dump文件发现都堆在了二代里,没有GC,具体都是堆在了异步方法里。

P3J{XA(E)L$@QE $GI8R%YL
image

和walterlv老哥聊了一下,需要具体查看下啥原因。

由于对性能这方面不是特别熟悉,不知道是不是我用法的问题,理论上在do方法里哪怕用了linq 生成了数据的copy ,方法执行完 应该自动释放掉,哪怕不是立即释放 也会隔一段时间释放,测试是不断上涨,隔了一晚上也没释放,主动GC,也GC不下来。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.