zoukankan      html  css  js  c++  java
  • 利用异步实现进度

      前些时间去面试,遇到面试官问我在一个任务中实现进度效果。

      可能一部分人想到的就是文件上传下载利用js的插件就可以实现了,cs模式也是有相应的插件的去实现,但实际上需求是希望实现某项操作,比如大型数据的计算,可能不是一时半会能完成的,也不能让客户分步骤去完成。

       首先我们要将任务分段,如果是有序的任务,比较好处理,比如批量对某些数据进行操作,那么可以根据数据的条数为总量除以完成数量得到任务执行百分比,如果是无序的,就只能对任务进行分段,根据每段的执行时间做一个任务占比的处理。

       而如何获取这些完成的百分比,有两种方式,一种是利用websocket或者SignalR回传完成的百分比,这个是同步的情况。

       另外一种可以利用异步去实现,这是接下来要介绍的。

       首先我们要创建一个异步线程任务:(ps:SmartThreadPool 智能线程池,可以在NuGet查询添加)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Amib.Threading;
    
    namespace Task
    {
        public interface IAsyncTask
        {
            AsyncTaskProgress AsyncTaskProgress { get; set; }
    
            WorkItemPriority Priority { get; set; }
    
            string TaskKey { get; set; }
    
            bool IsAuto { get; set; }
    
            void Queue();
    
            void Execute();
    
            void Prepareing();
    
            void Processing();
    
            void Exit();
    
            void ReStart();
    
            void Cancel();
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Task
    {
        public class AsyncTaskProgress
        {
            public AsyncTaskProgress() { }
    
            public AsyncTaskProgress(bool isPercentTask, decimal percent, string message)
            {
                IsPercentTask = isPercentTask;
                Percent = percent;
                Message = message;
            }
    
            public bool IsPercentTask { get; set; }
    
            public decimal Percent { get; set; }
    
            public string Message { get; set; }
    
            public AsyncTaskProgressState State { get; set; }
    
            public bool IsFinish
            {
                get
                {
                    return State == AsyncTaskProgressState.Success
                        || State == AsyncTaskProgressState.Cancel
                        || State == AsyncTaskProgressState.Error;
                }
            }
        }
    }

    将这个调度任务装进异步线程任务池里面,

    using System;
    using System.Collections.Generic;
    using System.Dynamic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using Amib.Threading;
    
    namespace Task
    {
        /// <summary>
        /// 创建线程池
        /// </summary>
        public class AsyncTaskPool
        {
            public static Dictionary<string, IAsyncTask> Tasks { get; set; }
    
            public static SmartThreadPool SmartThreadPool { get; set; }
    
            public static object Object = new object();
    
            static AsyncTaskPool()
            {
                Tasks = new Dictionary<string, IAsyncTask>();
                SmartThreadPool = new SmartThreadPool();
            }
    
            public static IWorkItemResult AddTask(IAsyncTask task)
            {
                lock (Object)
                {
                    if (Tasks.ContainsKey(task.TaskKey))
                    {
                        if (Tasks[task.TaskKey].AsyncTaskProgress.IsFinish)
                        {
                            Tasks.Remove(task.TaskKey);
                        }
                        else
                        {
                            throw new Exception("该任务已存在!");
                        }
                    }
                    Tasks.Add(task.TaskKey, task);
                    return SmartThreadPool.QueueWorkItem(task.Execute, task.Priority);
                }
            }
    
            public static IAsyncTask GeTask(string key)
            {
                if (Tasks.ContainsKey(key))
                {
                    return Tasks[key];
                }
                else
                {
                    throw new Exception("该任务不存在!");
                }
            }
    
            public static bool Remove(string key)
            {
                if (Tasks.ContainsKey(key))
                {
                    return Tasks.Remove(key);
                }
    
                return true;
            }
    
            public static bool Cancel(string key)
            {
                if (Tasks.ContainsKey(key))
                {
                    Tasks[key].Cancel();
                }
    
                return Remove(key);
            }
        }
    }

      

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Amib.Threading;
    
    namespace Task
    {
        public class BaseAsyncTask : IAsyncTask
        {
    
    
            public BaseAsyncTask(string key, bool isAuto, WorkItemPriority priority = WorkItemPriority.Normal, bool isAutoRecovery = false)
            {
                TaskKey = key;
                IsAuto = isAuto;
                Priority = priority;
                IsAutoRecovery = isAutoRecovery;
            }
    
            public AsyncTaskProgress AsyncTaskProgress { get; set; }
    
    
            public WorkItemPriority Priority { get; set; }
    
            /// <summary>
            /// 是否在异常的情况下自动重启
            /// </summary>
            public bool IsAutoRecovery { get; set; }
    
            public string TaskKey { get; set; }
    
    
            public bool IsAuto { get; set; }
    
    
            public void Queue()
            {
                AsyncTaskPool.AddTask(this);
            }
    
            public virtual void Execute()
            {
    
                try
                {
                    Prepareing();
                    Processing();
                }
                catch (Exception)
                {
                    //日志记录异常
                    throw;
                }
                finally
                {
                    if (IsAuto)
                        Exit(); //这里不能释放,不然100%的时候无法捕捉,需要捕捉到100%的时候去释放
                }
            }
    
            public void Prepareing()
            {
                Console.WriteLine("开始执行任务...");
            }
    
            public virtual void Processing() { }
    
            public void Exit()
            {
                AsyncTaskPool.Remove(this.TaskKey);
            }
    
            public void ReStart()
            {
                AsyncTaskPool.Cancel(this.TaskKey);
                AsyncTaskPool.AddTask(this);
            }
    
            public virtual void Cancel()
            {
                AsyncTaskPool.Cancel(this.TaskKey);
            }
        }
    }

    简单的调用

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Remoting.Channels;
    using System.Text;
    using System.Threading;
    using Amib.Threading;
    
    namespace Tack
    {
        public class DalculateMaxDataTask : BaseAsyncTask
        {
            public DalculateMaxDataTask(string key, bool isAuto, WorkItemPriority priority = WorkItemPriority.Normal, bool isAutoRecovery = false)
                : base(key, isAuto, priority, false)
            {
                AsyncTaskProgress = new AsyncTaskProgress();
            }
    
            public override void Processing()
            {
    
                AsyncTaskProgress.Percent = 0;
    
                Thread.Sleep(2000);
                AsyncTaskProgress.Percent = 10;
                Thread.Sleep(2000);
                AsyncTaskProgress.Percent = 20;
    
                Thread.Sleep(2000);
                AsyncTaskProgress.Percent = 30;
                Thread.Sleep(2000);
                AsyncTaskProgress.Percent = 100;
            }
    
        }
    }

    实际调用以及结果

      

  • 相关阅读:
    数据结构化与保存
    使用正则表达式,取得点击次数,函数抽离
    爬取校园新闻首页的新闻
    网络爬虫基础练习
    Hadoop综合大作业
    理解MapReduce
    熟悉常用的HBase操作
    熟悉常用的HDFS操作
    爬虫大作业
    数据结构化与保存
  • 原文地址:https://www.cnblogs.com/lhll/p/9952503.html
Copyright © 2011-2022 走看看