• Wpf实现图片自动轮播自定义控件


    近来,公司项目需要,需要写一个自定义控件,然后就有下面的控件产生。
    样式没有定义好,基本功能已经实现。
    1.创建为自定义控件的xaml页面。
    下面为后台代码
     
      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 using System.Threading;
      6 using System.Windows;
      7 using System.Windows.Controls;
      8 using System.Windows.Data;
      9 using System.Windows.Documents;
     10 using System.Windows.Input;
     11 using System.Windows.Media;
     12 using System.Windows.Media.Animation;
     13 using System.Windows.Media.Imaging;
     14 using System.Windows.Navigation;
     15 using System.Windows.Shapes;
     16 using System.Windows.Threading;
     17 
     18 namespace EZ.AppPlatform.App.VideoSummary.UserControl
     19 {
     20     /// <summary>
     21     /// AdvertPicControl.xaml 的交互逻辑
     22     /// </summary>
     23     public partial class AdvertPicControl : System.Windows.Controls.UserControl
     24     {
     25         #region 加载List数据
     26         /// <summary>
     27         /// 当前图片地址播放列表
     28         /// </summary>
     29         private static List<string> currentList;
     30 
     31         public static DependencyProperty advertPicList = DependencyProperty.Register("advertPicList", typeof(List<string>), typeof(AdvertPicControl)
     32             , new PropertyMetadata(new PropertyChangedCallback(loadAdvertPic)));
     33 
     34         public List<string> AdvertPicList
     35         {
     36             get { return (List<string>)GetValue(advertPicList); }
     37             set { SetValue(advertPicList, value); }
     38         }
     39 
     40         /// <summary>
     41         /// 图片播放器地址
     42         /// </summary>
     43         /// <param name="sender"></param>
     44         /// <param name="e"></param>
     45         private static void loadAdvertPic(DependencyObject sender, DependencyPropertyChangedEventArgs e)
     46         {
     47             AdvertPicControl advertPicControl = (AdvertPicControl)sender;
     48             if (e.Property == advertPicList)
     49             {
     50                 advertPicControl.AdvertPicList = (List<string>)e.NewValue;
     51                 currentList = advertPicControl.AdvertPicList;
     52             }
     53         }
     54         #endregion
     55 
     56         #region 加载图片停留时间
     57         /// <summary>
     58         /// 当前图片地址播放列表
     59         /// </summary>
     60         private static List<int> currentTimeList;
     61 
     62         public static DependencyProperty advertPicStayTime = DependencyProperty.Register("advertPicStayTime", typeof(List<int>), typeof(AdvertPicControl)
     63             , new PropertyMetadata(new PropertyChangedCallback(loadAdvertStayTime)));
     64 
     65         public List<int> AdvertPicStayTime
     66         {
     67             get { return (List<int>)GetValue(advertPicStayTime); }
     68             set { SetValue(advertPicStayTime, value); }
     69         }
     70 
     71         /// <summary>
     72         /// 图片播放器图片停留时间
     73         /// </summary>
     74         /// <param name="sender"></param>
     75         /// <param name="e"></param>
     76         private static void loadAdvertStayTime(DependencyObject sender, DependencyPropertyChangedEventArgs e)
     77         {
     78             AdvertPicControl advertPicControl = (AdvertPicControl)sender;
     79             if (e.Property == advertPicStayTime)
     80             {
     81                 advertPicControl.AdvertPicStayTime = (List<int>)e.NewValue;
     82                 currentTimeList = advertPicControl.AdvertPicStayTime;
     83             }
     84         }
     85         #endregion
     86 
     87         #region 注册自定义事件和参数
     88         public static readonly RoutedEvent AdvertPicPlayStateChangedEvent;
     89 
     90         public class AdvertPicPlayEventArgs : RoutedEventArgs
     91         {
     92             public int playState
     93             {
     94                 get;
     95                 set;
     96             }
     97 
     98             public int playLength
     99             {
    100                 get;
    101                 set;
    102             }
    103 
    104             public int playIndex
    105             {
    106                 get;
    107                 set;
    108             }
    109         }
    110 
    111         static AdvertPicControl()
    112         {
    113             AdvertPicPlayStateChangedEvent = EventManager.RegisterRoutedEvent("AdvertPicPlayStateChanged",
    114                 RoutingStrategy.Bubble, typeof(AdvertPicPlayStateChangedHandler), typeof(AdvertPicControl));
    115         }
    116         public delegate void AdvertPicPlayStateChangedHandler(object sender, AdvertPicPlayEventArgs e);
    117         public event AdvertPicPlayStateChangedHandler AdvertPicPlayStateChanged
    118         {
    119             add { AddHandler(AdvertPicControl.AdvertPicPlayStateChangedEvent, value); }
    120             remove { RemoveHandler(AdvertPicControl.AdvertPicPlayStateChangedEvent, value); }
    121         }
    122         #endregion
    123 
    124         #region 动态加载对应的切换图片按钮,单击响应加载对应的图片。
    125 
    126         #endregion
    127 
    128         public AdvertPicControl()
    129         {
    130             InitializeComponent();
    131         }
    132 
    133         DispatcherTimer switchPicTimer = new DispatcherTimer();
    134         int i = 0;
    135         private void UserControl_Loaded(object sender, RoutedEventArgs e)
    136         {
    137             //默认 1秒切换一张图片
    138            // switchPicTimer.IsEnabled = false;
    139         
    140             switchPicTimer.Tick += SwitchPicEvent;
    141             for (int j = 0; j < currentList.Count; j++)
    142             {
    143                Button btn=new Button();
    144                 btn.Width = 20;
    145                 btn.Height = 20;
    146                 btn.Content = j+1;
    147                 btn.Tag = j;
    148                 btn.Click+=new RoutedEventHandler(btn_Click);
    149                 PicCountNum.Children.Add(btn);
    150             }
    151          
    152         }
    153 
    154         void btn_Click(object sender, RoutedEventArgs e)
    155         {
    156             Button btn = (Button) sender;
    157             BitmapImage bitmap = new BitmapImage(new Uri(currentList[Convert.ToInt32( btn.Tag)], UriKind.Absolute));
    158             imgAdvertPic.Stretch = Stretch.Fill;
    159             imgAdvertPic.Source = bitmap;
    160         }
    161 
    162         /// <summary>
    163         /// 开始播放
    164         /// </summary>
    165         /// <param name="interval">图片切换时间</param>
    166         public void Play(int interval)
    167         {
    168             int defaultinterval = 0;
    169             if (interval != 0)
    170                 defaultinterval = interval;
    171 
    172             switchPicTimer.IsEnabled = true;
    173             switchPicTimer.Interval = new TimeSpan(0, 0, defaultinterval);
    174             switchPicTimer.Start();
    175             i = 0;
    176         }
    177 
    178         /// <summary>
    179         /// 停止播放
    180         /// </summary>
    181         public void Stop()
    182         {
    183             switchPicTimer.IsEnabled = false;
    184             switchPicTimer.Stop();
    185         }
    186 
    187         /// <summary>
    188         /// 切换图片事件
    189         /// </summary>
    190         /// <param name="sender"></param>
    191         /// <param name="e"></param>
    192         private void SwitchPicEvent(object sender, EventArgs e)
    193         {
    194             if (null != currentList)
    195             {
    196                // Console.WriteLine("开始切换~~~");
    197                 if (i <= currentList.Count-1)//修改实现循环播放。
    198                 {
    199                     DoHandlerStop(Image.OpacityProperty, 20, 0, 4, imgAdvertPic, SwitchPic);
    200                 }
    201                 else
    202                 {
    203                     //AdvertPicPlayEventArgs args = new AdvertPicPlayEventArgs();
    204                     //args.RoutedEvent = AdvertPicPlayStateChangedEvent;
    205                     //args.playState = 1;
    206                     //RaiseEvent(args);
    207                     // switchPicTimer.Stop();
    208                     // switchPicTimer.IsEnabled = false;
    209                     i = 0;
    210                     DoHandlerStop(Image.OpacityProperty, 20, 0, 4, imgAdvertPic, SwitchPic);
    211                  
    212                 }
    213                 if (null != currentTimeList)
    214                 {
    215                     Thread.Sleep(currentTimeList[i]); //图片停留时间
    216                 }
    217             }
    218         }
    219 
    220         /// <summary>
    221         /// 动画播放完毕切换图片
    222         /// </summary>
    223         /// <param name="sender"></param>
    224         /// <param name="e"></param>
    225         private void SwitchPic(object sender, EventArgs e)
    226         {
    227             BitmapImage bitmap = new BitmapImage(new Uri(currentList[i], UriKind.Absolute));
    228             imgAdvertPic.Stretch = Stretch.Fill;
    229             imgAdvertPic.Source = bitmap;
    230             if (i < currentList.Count)
    231             {
    232                 i++;
    233             }
    234           
    235         }
    236 
    237         public void ClickToPic(int id)
    238         {
    239           
    240         }
    241 
    242 
    243         /// <summary>
    244         /// 动画
    245         /// </summary>
    246         /// <param name="dp"></param>
    247         /// <param name="from"></param>
    248         /// <param name="to"></param>
    249         /// <param name="duration"></param>
    250         /// <param name="element"></param>
    251         /// <param name="complateHander"></param>
    252         public void DoHandlerStop(DependencyProperty dp, double from, double to, double duration, UIElement element, EventHandler complateHander)
    253         {
    254             DoubleAnimation doubleAnimation = new DoubleAnimation();//创建双精度动画对象
    255             doubleAnimation.From = from;
    256             doubleAnimation.To = to;//设置动画的结束值
    257             doubleAnimation.Duration = TimeSpan.FromSeconds(duration);//设置动画时间线长度
    258             doubleAnimation.FillBehavior = FillBehavior.Stop;//设置动画完成后执行的操作 
    259             doubleAnimation.Completed += complateHander;
    260             element.BeginAnimation(dp, doubleAnimation);//设置动画应用的属性并启动动画
    261         }
    262     }
    263 }
    View Code
    前台xaml代码:
      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 using System.Threading;
      6 using System.Windows;
      7 using System.Windows.Controls;
      8 using System.Windows.Data;
      9 using System.Windows.Documents;
     10 using System.Windows.Input;
     11 using System.Windows.Media;
     12 using System.Windows.Media.Animation;
     13 using System.Windows.Media.Imaging;
     14 using System.Windows.Navigation;
     15 using System.Windows.Shapes;
     16 using System.Windows.Threading;
     17 
     18 namespace EZ.AppPlatform.App.VideoSummary.UserControl
     19 {
     20     /// <summary>
     21     /// AdvertPicControl.xaml 的交互逻辑
     22     /// </summary>
     23     public partial class AdvertPicControl : System.Windows.Controls.UserControl
     24     {
     25         #region 加载List数据
     26         /// <summary>
     27         /// 当前图片地址播放列表
     28         /// </summary>
     29         private static List<string> currentList;
     30 
     31         public static DependencyProperty advertPicList = DependencyProperty.Register("advertPicList", typeof(List<string>), typeof(AdvertPicControl)
     32             , new PropertyMetadata(new PropertyChangedCallback(loadAdvertPic)));
     33 
     34         public List<string> AdvertPicList
     35         {
     36             get { return (List<string>)GetValue(advertPicList); }
     37             set { SetValue(advertPicList, value); }
     38         }
     39 
     40         /// <summary>
     41         /// 图片播放器地址
     42         /// </summary>
     43         /// <param name="sender"></param>
     44         /// <param name="e"></param>
     45         private static void loadAdvertPic(DependencyObject sender, DependencyPropertyChangedEventArgs e)
     46         {
     47             AdvertPicControl advertPicControl = (AdvertPicControl)sender;
     48             if (e.Property == advertPicList)
     49             {
     50                 advertPicControl.AdvertPicList = (List<string>)e.NewValue;
     51                 currentList = advertPicControl.AdvertPicList;
     52             }
     53         }
     54         #endregion
     55 
     56         #region 加载图片停留时间
     57         /// <summary>
     58         /// 当前图片地址播放列表
     59         /// </summary>
     60         private static List<int> currentTimeList;
     61 
     62         public static DependencyProperty advertPicStayTime = DependencyProperty.Register("advertPicStayTime", typeof(List<int>), typeof(AdvertPicControl)
     63             , new PropertyMetadata(new PropertyChangedCallback(loadAdvertStayTime)));
     64 
     65         public List<int> AdvertPicStayTime
     66         {
     67             get { return (List<int>)GetValue(advertPicStayTime); }
     68             set { SetValue(advertPicStayTime, value); }
     69         }
     70 
     71         /// <summary>
     72         /// 图片播放器图片停留时间
     73         /// </summary>
     74         /// <param name="sender"></param>
     75         /// <param name="e"></param>
     76         private static void loadAdvertStayTime(DependencyObject sender, DependencyPropertyChangedEventArgs e)
     77         {
     78             AdvertPicControl advertPicControl = (AdvertPicControl)sender;
     79             if (e.Property == advertPicStayTime)
     80             {
     81                 advertPicControl.AdvertPicStayTime = (List<int>)e.NewValue;
     82                 currentTimeList = advertPicControl.AdvertPicStayTime;
     83             }
     84         }
     85         #endregion
     86 
     87         #region 注册自定义事件和参数
     88         public static readonly RoutedEvent AdvertPicPlayStateChangedEvent;
     89 
     90         public class AdvertPicPlayEventArgs : RoutedEventArgs
     91         {
     92             public int playState
     93             {
     94                 get;
     95                 set;
     96             }
     97 
     98             public int playLength
     99             {
    100                 get;
    101                 set;
    102             }
    103 
    104             public int playIndex
    105             {
    106                 get;
    107                 set;
    108             }
    109         }
    110 
    111         static AdvertPicControl()
    112         {
    113             AdvertPicPlayStateChangedEvent = EventManager.RegisterRoutedEvent("AdvertPicPlayStateChanged",
    114                 RoutingStrategy.Bubble, typeof(AdvertPicPlayStateChangedHandler), typeof(AdvertPicControl));
    115         }
    116         public delegate void AdvertPicPlayStateChangedHandler(object sender, AdvertPicPlayEventArgs e);
    117         public event AdvertPicPlayStateChangedHandler AdvertPicPlayStateChanged
    118         {
    119             add { AddHandler(AdvertPicControl.AdvertPicPlayStateChangedEvent, value); }
    120             remove { RemoveHandler(AdvertPicControl.AdvertPicPlayStateChangedEvent, value); }
    121         }
    122         #endregion
    123 
    124         #region 动态加载对应的切换图片按钮,单击响应加载对应的图片。
    125 
    126         #endregion
    127 
    128         public AdvertPicControl()
    129         {
    130             InitializeComponent();
    131         }
    132 
    133         DispatcherTimer switchPicTimer = new DispatcherTimer();
    134         int i = 0;
    135         private void UserControl_Loaded(object sender, RoutedEventArgs e)
    136         {
    137             //默认 1秒切换一张图片
    138            // switchPicTimer.IsEnabled = false;
    139         
    140             switchPicTimer.Tick += SwitchPicEvent;
    141             for (int j = 0; j < currentList.Count; j++)
    142             {
    143                Button btn=new Button();
    144                 btn.Width = 20;
    145                 btn.Height = 20;
    146                 btn.Content = j+1;
    147                 btn.Tag = j;
    148                 btn.Click+=new RoutedEventHandler(btn_Click);
    149                 PicCountNum.Children.Add(btn);
    150             }
    151          
    152         }
    153 
    154         void btn_Click(object sender, RoutedEventArgs e)
    155         {
    156             Button btn = (Button) sender;
    157             BitmapImage bitmap = new BitmapImage(new Uri(currentList[Convert.ToInt32( btn.Tag)], UriKind.Absolute));
    158             imgAdvertPic.Stretch = Stretch.Fill;
    159             imgAdvertPic.Source = bitmap;
    160         }
    161 
    162         /// <summary>
    163         /// 开始播放
    164         /// </summary>
    165         /// <param name="interval">图片切换时间</param>
    166         public void Play(int interval)
    167         {
    168             int defaultinterval = 0;
    169             if (interval != 0)
    170                 defaultinterval = interval;
    171 
    172             switchPicTimer.IsEnabled = true;
    173             switchPicTimer.Interval = new TimeSpan(0, 0, defaultinterval);
    174             switchPicTimer.Start();
    175             i = 0;
    176         }
    177 
    178         /// <summary>
    179         /// 停止播放
    180         /// </summary>
    181         public void Stop()
    182         {
    183             switchPicTimer.IsEnabled = false;
    184             switchPicTimer.Stop();
    185         }
    186 
    187         /// <summary>
    188         /// 切换图片事件
    189         /// </summary>
    190         /// <param name="sender"></param>
    191         /// <param name="e"></param>
    192         private void SwitchPicEvent(object sender, EventArgs e)
    193         {
    194             if (null != currentList)
    195             {
    196                // Console.WriteLine("开始切换~~~");
    197                 if (i <= currentList.Count-1)//修改实现循环播放。
    198                 {
    199                     DoHandlerStop(Image.OpacityProperty, 20, 0, 4, imgAdvertPic, SwitchPic);
    200                 }
    201                 else
    202                 {
    203                     //AdvertPicPlayEventArgs args = new AdvertPicPlayEventArgs();
    204                     //args.RoutedEvent = AdvertPicPlayStateChangedEvent;
    205                     //args.playState = 1;
    206                     //RaiseEvent(args);
    207                     // switchPicTimer.Stop();
    208                     // switchPicTimer.IsEnabled = false;
    209                     i = 0;
    210                     DoHandlerStop(Image.OpacityProperty, 20, 0, 4, imgAdvertPic, SwitchPic);
    211                  
    212                 }
    213                 if (null != currentTimeList)
    214                 {
    215                     Thread.Sleep(currentTimeList[i]); //图片停留时间
    216                 }
    217             }
    218         }
    219 
    220         /// <summary>
    221         /// 动画播放完毕切换图片
    222         /// </summary>
    223         /// <param name="sender"></param>
    224         /// <param name="e"></param>
    225         private void SwitchPic(object sender, EventArgs e)
    226         {
    227             BitmapImage bitmap = new BitmapImage(new Uri(currentList[i], UriKind.Absolute));
    228             imgAdvertPic.Stretch = Stretch.Fill;
    229             imgAdvertPic.Source = bitmap;
    230             if (i < currentList.Count)
    231             {
    232                 i++;
    233             }
    234           
    235         }
    236 
    237         public void ClickToPic(int id)
    238         {
    239           
    240         }
    241 
    242 
    243         /// <summary>
    244         /// 动画
    245         /// </summary>
    246         /// <param name="dp"></param>
    247         /// <param name="from"></param>
    248         /// <param name="to"></param>
    249         /// <param name="duration"></param>
    250         /// <param name="element"></param>
    251         /// <param name="complateHander"></param>
    252         public void DoHandlerStop(DependencyProperty dp, double from, double to, double duration, UIElement element, EventHandler complateHander)
    253         {
    254             DoubleAnimation doubleAnimation = new DoubleAnimation();//创建双精度动画对象
    255             doubleAnimation.From = from;
    256             doubleAnimation.To = to;//设置动画的结束值
    257             doubleAnimation.Duration = TimeSpan.FromSeconds(duration);//设置动画时间线长度
    258             doubleAnimation.FillBehavior = FillBehavior.Stop;//设置动画完成后执行的操作 
    259             doubleAnimation.Completed += complateHander;
    260             element.BeginAnimation(dp, doubleAnimation);//设置动画应用的属性并启动动画
    261         }
    262     }
    263 }
    View Code

    2.创建主窗体:

    调用部分:

    xaml部分,一个grid控件

     1 <Window x:Class="EZ.AppPlatform.App.VideoSummary.TestPicscroll"
     2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     4         Title="TestPicscroll" Height="340" Width="594" Loaded="Window_Loaded">
     5     <Grid Width="579" Name="grdContent">
     6         <!--<Button  Content="Start" Height="23" HorizontalAlignment="Left" Margin="92,51,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
     7         <Button Content="Stop" Height="23" HorizontalAlignment="Right" Margin="0,51,263,0" Name="button2" VerticalAlignment="Top" Width="75" Click="button2_Click" />-->
     8    
     9     </Grid>
    10 </Window>
    View Code
    服务端代码部分。
      1 using System;
      2 using System.Collections.Generic;
      3 using System.IO;
      4 using System.Linq;
      5 using System.Text;
      6 using System.Windows;
      7 using System.Windows.Controls;
      8 using System.Windows.Data;
      9 using System.Windows.Documents;
     10 using System.Windows.Input;
     11 using System.Windows.Media;
     12 using System.Windows.Media.Imaging;
     13 using System.Windows.Shapes;
     14 using EZ.AppPlatform.App.VideoSummary.UserControl;
     15 
     16 namespace EZ.AppPlatform.App.VideoSummary
     17 {
     18     /// <summary>
     19     /// TestPicscroll.xaml 的交互逻辑
     20     /// </summary>
     21     public partial class TestPicscroll : Window
     22     {
     23         public TestPicscroll()
     24         {
     25             InitializeComponent();
     26         }
     27         /// <summary>
     28         /// 获取当前用户的图片文件夹中的图片(不包含子文件夹)
     29         /// </summary>
     30         /// <returns>返回图片路径列表</returns>
     31         private List<string> GetUserImages(string path)
     32         {
     33             List<string> images = new List<string>();
     34            //Environment.GetFolderPath();//Environment.SpecialFolder.MyPictures
     35             DirectoryInfo dir = new DirectoryInfo(path);
     36             FileInfo[] files = GetPicFiles(path, "*.jpg,*.png,*.bmp,*.gif,", SearchOption.TopDirectoryOnly);// dir.GetFiles("*.jpg", SearchOption.AllDirectories);
     37 
     38             if (files != null)
     39             {
     40                 foreach (FileInfo file in files)
     41                 {
     42                     images.Add(file.FullName);
     43                 }
     44             }
     45             return images;
     46         }
     47 
     48         public FileInfo[] GetPicFiles(string picPath, string searchPattern, SearchOption searchOption)
     49         {
     50             System.Collections.Generic.List<FileInfo> ltList = new List<FileInfo>();
     51             DirectoryInfo dir = new DirectoryInfo(picPath);
     52             string[] sPattern = searchPattern.Replace(';', ',').Split(',');
     53             for (int i = 0; i < sPattern.Length; i++)
     54             {
     55                 FileInfo[] files = null;
     56                 try
     57                 {
     58                     files = dir.GetFiles(sPattern[i], searchOption);
     59                 }
     60                 catch (System.Exception ex)
     61                 {
     62                     files = new FileInfo[] { };
     63                 }
     64 
     65                 ltList.AddRange(files);
     66             }
     67             return ltList.ToArray();
     68         }
     69         AdvertPicControl advertPic = new AdvertPicControl();
     70         string path = @"E:ProjectSourceAppDeskEZ.AppPlatform.App.VideoSummaryAssetsImages	em"; 
     71         private void Window_Loaded(object sender, RoutedEventArgs e)
     72         {
     73             List<string> imageList = GetUserImages(path);
     74             advertPic.AdvertPicList = imageList;// this.GetUserImages();
     75             grdContent.Children.Add(advertPic);
     76             advertPic.AdvertPicPlayStateChanged += playStateHandler;
     77            advertPic.Play(2);
     78         }
     79 
     80 
     81         private void playStateHandler(object sender, AdvertPicControl.AdvertPicPlayEventArgs args)
     82         {
     83            // MessageBox.Show("播放完了,触发事件....");
     84             advertPic.Stop();
     85            advertPic.Play(2);
     86         }
     87 
     88       ///// <summary>
     89       ///// 开始播放
     90       ///// </summary>
     91       ///// <param name="sender"></param>
     92       ///// <param name="e"></param>
     93       //  private void button1_Click(object sender, RoutedEventArgs e)
     94       //  {
     95       //      advertPic.Play(Convert.ToInt32(2)); //设置默认切换时间
     96       //  }
     97       //  /// <summary>
     98       //  /// 停止播放
     99       //  /// </summary>
    100       //  /// <param name="sender"></param>
    101       //  /// <param name="e"></param>
    102       //  private void button2_Click(object sender, RoutedEventArgs e)
    103       //  {
    104       //      advertPic.Stop();
    105       //  }
    106     }
    107 }
    View Code

     然后设置app.xaml启动项为主窗体,然后运行,默认为2s切换一次。

  • 相关阅读:
    spring cglib final @Transactional
    【转】电商架构
    logback发邮件配置
    @Reference不支持继承
    jmap jstack
    dubbo线程池
    C# 爬虫框架实现 流程_爬虫结构/原理
    C# 爬虫框架实现 流程_各个类开发
    C# 爬虫框架实现 概述
    作用域 作用域链 闭包 思想 JS/C++比较
  • 原文地址:https://www.cnblogs.com/gxg2008540/p/wpf.html
Copyright © 2020-2023  润新知