11 | {
12 | ///
13 | ///
14 | ///
15 | /// 是否保持(长)连接,即自动管理连接
16 | /// 是否使用事务,即自动管理事务
17 | public MyAdvice(bool keepConnection, bool useTransaction)
18 | : base(keepConnection, useTransaction)
19 | {
20 |
21 | }
22 |
23 |
24 |
25 | ///
26 | /// 保持连接
27 | ///
28 | ///
29 | public static MyAdvice GetKeepConnection()
30 | {
31 | return new MyAdvice(true, false);
32 | }
33 |
34 | ///
35 | /// 开启事务
36 | ///
37 | ///
38 | public static MyAdvice GetUseTransaction()
39 | {
40 | return new MyAdvice(true, true);
41 | }
42 |
43 |
44 |
45 | #region Override
46 |
47 | protected override void OpenConnection()
48 | {
49 | Console.WriteLine("打开连接");
50 | }
51 |
52 | protected override void CloseConnection()
53 | {
54 | Console.WriteLine("关闭连接");
55 | }
56 |
57 | protected override void BeginTransaction(bool onlyBeginTransaction)
58 | {
59 | Console.WriteLine("开启事务");
60 | }
61 |
62 | protected override void CommitTransaction(bool onlyCommitTransaction)
63 | {
64 | Console.WriteLine("提交事务");
65 | }
66 |
67 | protected override void RollBackTransaction(bool onlyRollBackTransaction)
68 | {
69 | Console.WriteLine("回滚事务");
70 | }
71 |
72 | protected override bool HasOpenConnection()
73 | {
74 | Console.WriteLine("打开连接");
75 | // TODO
76 | return false;
77 | }
78 |
79 | protected override bool HasBeginTransaction()
80 | {
81 | Console.WriteLine("开启事务");
82 | // TODO
83 | return false;
84 | }
85 |
86 | #endregion
87 |
88 | }
89 | }
--------------------------------------------------------------------------------
/AOPDemo/Common/ServiceAbstract.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Web;
5 |
6 | namespace AOPDemo.Common
7 | {
8 |
9 | ///
10 | /// 扩展的抽象服务类
11 | /// 配合增强类,完成以下功能:
12 | /// 1、自动管理数据库连接[可选]
13 | /// 2、自动管理数据库事务,当接收到异常后(无论什么异常)事务将自动回滚[可选]
14 | ///
15 | /// 3、服务级加锁[必选]
16 | /// 4、以统一方式处理服务异常及错误处理,包括数据库异常 和 主动抛出的异常[必选]
17 | ///
18 | public abstract class ServiceAbstract : MarshalByRefObject
19 | {
20 | ///
21 | /// 是否发生错误
22 | ///
23 | public bool Error { get; protected set; }
24 |
25 | ///
26 | /// 错误提示信息(友好的,用户可见)
27 | ///
28 | public string ErrorMsg { get; protected set; }
29 |
30 | ///
31 | /// 错误详情
32 | /// 所有错误,均通过异常抛出
33 | ///
34 | public Exception ErrorEx { get; protected set; }
35 |
36 |
37 |
38 | ///
39 | /// 重置错误信息
40 | ///
41 | public void ResetError()
42 | {
43 | this.Error = false;
44 | this.ErrorMsg = string.Empty;
45 | this.ErrorEx = null;
46 | }
47 |
48 | ///
49 | /// 设置错误信息
50 | ///
51 | ///
52 | ///
53 | public void SetError(string msg, Exception ex)
54 | {
55 | this.Error = true;
56 | this.ErrorEx = ex;
57 | this.ErrorMsg = msg;
58 | }
59 |
60 |
61 | ///
62 | /// 获取服务级别的锁定对象,以完成系统应用层加锁(具体而言是Service层加锁)
63 | ///
64 | ///
65 | public abstract object GetLockObject();
66 |
67 | }
68 |
69 | }
--------------------------------------------------------------------------------
/AOPDemo/Common/ServiceExecption.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Web;
5 |
6 | namespace AOPDemo.Common
7 | {
8 |
9 | ///
10 | /// 自定义的服务异常
11 | ///
12 | [Serializable]
13 | public class ServiceException : Exception
14 | {
15 | ///
16 | /// 为异常提供附加数据
17 | /// 用户不可见
18 | ///
19 | public int Code { get; set; }
20 |
21 | ///
22 | /// 为异常提供附加数据
23 | /// 用户不可见
24 | ///
25 | public string Tag { get; set; }
26 |
27 | public ServiceException() { }
28 | public ServiceException(string message) : base(message) { }
29 | public ServiceException(string message, Exception inner) : base(message, inner) { }
30 | protected ServiceException(
31 | System.Runtime.Serialization.SerializationInfo info,
32 | System.Runtime.Serialization.StreamingContext context)
33 | : base(info, context) { }
34 | }
35 |
36 |
37 | }
--------------------------------------------------------------------------------
/AOPDemo/Controllers/HomeController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Web;
5 | using System.Web.Mvc;
6 | using AOPDemo.Common;
7 |
8 | namespace AOPDemo.Controllers
9 | {
10 | public class HomeController : Controller
11 | {
12 | ///
13 | /// 使用 Autowired Attribute 自动初始化代理对象
14 | ///
15 | [Autowired]
16 | public Service myService { get; set; }
17 |
18 |
19 | public ActionResult Index()
20 | {
21 | myService.Test();
22 |
23 | var msg = myService.ErrorMsg;
24 | Console.WriteLine(msg);
25 |
26 | // 当然 ServiceException 中的 Code属性也可以存储在 ServiceAbstract 对象中
27 |
28 | return View();
29 | }
30 | }
31 |
32 |
33 | public class Service : ServiceAbstract
34 | {
35 | #region 自动加锁
36 |
37 | private static object objLock = new object();
38 |
39 | public override object GetLockObject()
40 | {
41 | return objLock;
42 | }
43 |
44 | #endregion
45 |
46 |
47 | ///
48 | /// 自动开启事务
49 | ///
50 | [Advice(typeof(MyAdvice), "GetUseTransaction")]
51 | public void Test()
52 | {
53 | Console.WriteLine("调用Test方法,在调用方法前开启事务,调用方法后提交或回滚事务");
54 |
55 | throw new ServiceException("发生异常,回滚事务") { Code = 999 };
56 | }
57 | }
58 |
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/AOPDemo/Global.asax:
--------------------------------------------------------------------------------
1 | <%@ Application Codebehind="Global.asax.cs" Inherits="AOPDemo.MvcApplication" Language="C#" %>
2 |
--------------------------------------------------------------------------------
/AOPDemo/Global.asax.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Web;
5 | using System.Web.Http;
6 | using System.Web.Http.Dispatcher;
7 | using System.Web.Http.Controllers;
8 | using System.Net.Http;
9 | using System.Web.Mvc;
10 | using System.Web.Routing;
11 | using AOPDemo.Common;
12 |
13 | namespace AOPDemo
14 | {
15 | // Note: For instructions on enabling IIS6 or IIS7 classic mode,
16 | // visit http://go.microsoft.com/?LinkId=9394801
17 | public class MvcApplication : System.Web.HttpApplication
18 | {
19 | protected void Application_Start()
20 | {
21 | // 注册新的Controller工厂
22 | ControllerBuilder.Current.SetControllerFactory(new MyBatisControllerFactory());
23 |
24 | // 使AOP适应 WebApi
25 | GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new MyHttpControllerActivator());
26 |
27 | AreaRegistration.RegisterAllAreas();
28 |
29 | WebApiConfig.Register(GlobalConfiguration.Configuration);
30 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
31 | RouteConfig.RegisterRoutes(RouteTable.Routes);
32 | }
33 |
34 |
35 |
36 | private class MyBatisControllerFactory : DefaultControllerFactory
37 | {
38 | public override IController CreateController(RequestContext requestContext, string controllerName)
39 | {
40 | IController controller = base.CreateController(requestContext, controllerName);
41 |
42 | /// 自动装配属性
43 | /// 为属性对象启用代理,并延迟初始化被代理的对象
44 | DelayProxyUtil.AutowiredProperties(controller);
45 |
46 | return controller;
47 | }
48 | }
49 |
50 |
51 |
52 | ///
53 | /// 用于Web Api
54 | ///
55 | private class MyHttpControllerActivator : IHttpControllerActivator
56 | {
57 | private DefaultHttpControllerActivator defaultActivator;
58 |
59 | public MyHttpControllerActivator()
60 | {
61 | this.defaultActivator = new DefaultHttpControllerActivator();
62 | }
63 |
64 | public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
65 | {
66 | IHttpController httpController = this.defaultActivator.Create(request, controllerDescriptor, controllerType);
67 |
68 | if (httpController != null)
69 | {
70 | /// 自动装配属性
71 | /// 为属性对象启用代理,并延迟初始化被代理的对象
72 | DelayProxyUtil.AutowiredProperties(httpController);
73 | }
74 |
75 | return httpController;
76 | }
77 | }
78 |
79 |
80 | }
81 |
82 |
83 |
84 | }
--------------------------------------------------------------------------------
/AOPDemo/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的常规信息通过下列特性集
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("AOPDemo")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Microsoft")]
12 | [assembly: AssemblyProduct("AOPDemo")]
13 | [assembly: AssemblyCopyright("版权所有(C) Microsoft 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 会使此程序集中的类型
18 | // 对 COM 组件不可见。如果需要从 COM 访问此程序集中的某个类型,
19 | // 请针对该类型将 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("aafe6fea-5f28-4cb1-825d-413959df74ca")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 内部版本号
30 | // 修订号
31 | //
32 | // 可以指定所有这些值,也可以使用“修订号”和“内部版本号”的默认值,
33 | // 方法是按如下所示使用“*”:
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
36 |
--------------------------------------------------------------------------------
/AOPDemo/Views/Home/Index.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | ViewBag.Title = "Index";
3 | }
4 |
5 | 本Demo使用RealProxy实现了简单的AOP
6 | 此外,自定义了AutowiredAttribute,标记该属性会自动初始化,当然也支持延迟初始化
7 | 自己实现简单的AOP(一)简介
8 | 自己实现简单的AOP(二)引入Attribute 为方法指定增强对象
9 | 自己实现简单的AOP(三) 实现增强四项基本功能
10 | 自己实现简单的AOP(四)自动初始化代理对象
11 | 自己实现简单的AOP(五)使Demo适应webApi、亦可完成属性自动注入
12 |
13 |
--------------------------------------------------------------------------------
/AOPDemo/Views/Web.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
39 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/AOPDemo/Web.Debug.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
29 |
30 |
--------------------------------------------------------------------------------
/AOPDemo/Web.Release.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
19 |
30 |
31 |
--------------------------------------------------------------------------------
/AOPDemo/Web.config:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/AOPDemo/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/BlogsDemo.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NET", "NET", "{9125DCFF-2041-40FA-8B4D-D19EB77F7B24}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WPF", "WPF", "{942427F4-3BE9-49F4-9084-86CE08406A89}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WinForm", "WinForm", "{86F3FF10-931E-4B6C-B114-F4305A9E3E3C}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParallelDemo", "ParallelDemo\ParallelDemo.csproj", "{6D3C0CF4-4029-4E7A-A33E-B0D038B3BF92}"
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginDemo", "PluginDemo\PluginDemo.csproj", "{803E039B-BF06-4D35-966F-0BC4A96D4A98}"
15 | EndProject
16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AOPDemo", "AOPDemo\AOPDemo.csproj", "{04412CBA-9B27-4A99-BEA9-8432CB370055}"
17 | EndProject
18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginDemo.NewDomain", "PluginDemo.NewDomain\PluginDemo.NewDomain.csproj", "{60D4EE42-C507-41B3-ADF5-432AD02A6FED}"
19 | EndProject
20 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DropDownCustomColorPicker", "DropDownCustomColorPicker\DropDownCustomColorPicker.csproj", "{FD2EC7D4-4316-4F8F-8108-8381F0B4B340}"
21 | EndProject
22 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DropDownCustomColorPicker.Test", "DropDownCustomColorPicker.Test\DropDownCustomColorPicker.Test.csproj", "{46B3AA45-E0B3-4D68-B91A-878D2DA7A0C9}"
23 | EndProject
24 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B8C7778C-C449-4D34-86C1-6AA314A3AC84}"
25 | ProjectSection(SolutionItems) = preProject
26 | readme.txt = readme.txt
27 | EndProjectSection
28 | EndProject
29 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CaptureWindowDemo", "CaptureWindowDemo\CaptureWindowDemo.csproj", "{5F8BE534-08E0-488A-B2A6-DA301C3E91FA}"
30 | EndProject
31 | Global
32 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
33 | Debug|Any CPU = Debug|Any CPU
34 | Release|Any CPU = Release|Any CPU
35 | EndGlobalSection
36 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
37 | {6D3C0CF4-4029-4E7A-A33E-B0D038B3BF92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
38 | {6D3C0CF4-4029-4E7A-A33E-B0D038B3BF92}.Debug|Any CPU.Build.0 = Debug|Any CPU
39 | {6D3C0CF4-4029-4E7A-A33E-B0D038B3BF92}.Release|Any CPU.ActiveCfg = Release|Any CPU
40 | {6D3C0CF4-4029-4E7A-A33E-B0D038B3BF92}.Release|Any CPU.Build.0 = Release|Any CPU
41 | {803E039B-BF06-4D35-966F-0BC4A96D4A98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
42 | {803E039B-BF06-4D35-966F-0BC4A96D4A98}.Debug|Any CPU.Build.0 = Debug|Any CPU
43 | {803E039B-BF06-4D35-966F-0BC4A96D4A98}.Release|Any CPU.ActiveCfg = Release|Any CPU
44 | {803E039B-BF06-4D35-966F-0BC4A96D4A98}.Release|Any CPU.Build.0 = Release|Any CPU
45 | {04412CBA-9B27-4A99-BEA9-8432CB370055}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
46 | {04412CBA-9B27-4A99-BEA9-8432CB370055}.Debug|Any CPU.Build.0 = Debug|Any CPU
47 | {04412CBA-9B27-4A99-BEA9-8432CB370055}.Release|Any CPU.ActiveCfg = Release|Any CPU
48 | {04412CBA-9B27-4A99-BEA9-8432CB370055}.Release|Any CPU.Build.0 = Release|Any CPU
49 | {60D4EE42-C507-41B3-ADF5-432AD02A6FED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
50 | {60D4EE42-C507-41B3-ADF5-432AD02A6FED}.Debug|Any CPU.Build.0 = Debug|Any CPU
51 | {60D4EE42-C507-41B3-ADF5-432AD02A6FED}.Release|Any CPU.ActiveCfg = Release|Any CPU
52 | {60D4EE42-C507-41B3-ADF5-432AD02A6FED}.Release|Any CPU.Build.0 = Release|Any CPU
53 | {FD2EC7D4-4316-4F8F-8108-8381F0B4B340}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
54 | {FD2EC7D4-4316-4F8F-8108-8381F0B4B340}.Debug|Any CPU.Build.0 = Debug|Any CPU
55 | {FD2EC7D4-4316-4F8F-8108-8381F0B4B340}.Release|Any CPU.ActiveCfg = Release|Any CPU
56 | {FD2EC7D4-4316-4F8F-8108-8381F0B4B340}.Release|Any CPU.Build.0 = Release|Any CPU
57 | {46B3AA45-E0B3-4D68-B91A-878D2DA7A0C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
58 | {46B3AA45-E0B3-4D68-B91A-878D2DA7A0C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
59 | {46B3AA45-E0B3-4D68-B91A-878D2DA7A0C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
60 | {46B3AA45-E0B3-4D68-B91A-878D2DA7A0C9}.Release|Any CPU.Build.0 = Release|Any CPU
61 | {5F8BE534-08E0-488A-B2A6-DA301C3E91FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
62 | {5F8BE534-08E0-488A-B2A6-DA301C3E91FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
63 | {5F8BE534-08E0-488A-B2A6-DA301C3E91FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
64 | {5F8BE534-08E0-488A-B2A6-DA301C3E91FA}.Release|Any CPU.Build.0 = Release|Any CPU
65 | EndGlobalSection
66 | GlobalSection(SolutionProperties) = preSolution
67 | HideSolutionNode = FALSE
68 | EndGlobalSection
69 | GlobalSection(NestedProjects) = preSolution
70 | {6D3C0CF4-4029-4E7A-A33E-B0D038B3BF92} = {9125DCFF-2041-40FA-8B4D-D19EB77F7B24}
71 | {803E039B-BF06-4D35-966F-0BC4A96D4A98} = {9125DCFF-2041-40FA-8B4D-D19EB77F7B24}
72 | {04412CBA-9B27-4A99-BEA9-8432CB370055} = {9125DCFF-2041-40FA-8B4D-D19EB77F7B24}
73 | {60D4EE42-C507-41B3-ADF5-432AD02A6FED} = {9125DCFF-2041-40FA-8B4D-D19EB77F7B24}
74 | {FD2EC7D4-4316-4F8F-8108-8381F0B4B340} = {942427F4-3BE9-49F4-9084-86CE08406A89}
75 | {46B3AA45-E0B3-4D68-B91A-878D2DA7A0C9} = {942427F4-3BE9-49F4-9084-86CE08406A89}
76 | {5F8BE534-08E0-488A-B2A6-DA301C3E91FA} = {9125DCFF-2041-40FA-8B4D-D19EB77F7B24}
77 | EndGlobalSection
78 | EndGlobal
79 |
--------------------------------------------------------------------------------
/CaptureWindowDemo/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/CaptureWindowDemo/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Linq;
6 | using System.Windows;
7 |
8 | namespace CaptureWindowDemo
9 | {
10 | ///
11 | /// App.xaml 的交互逻辑
12 | ///
13 | public partial class App : Application
14 | {
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/CaptureWindowDemo/CaptureWindowDemo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {5F8BE534-08E0-488A-B2A6-DA301C3E91FA}
8 | WinExe
9 | Properties
10 | CaptureWindowDemo
11 | CaptureWindowDemo
12 | v4.0
13 | 512
14 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
15 | 4
16 |
17 |
18 | AnyCPU
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 |
27 |
28 | AnyCPU
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | 4.0
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | MSBuild:Compile
55 | Designer
56 |
57 |
58 | MSBuild:Compile
59 | Designer
60 |
61 |
62 | App.xaml
63 | Code
64 |
65 |
66 |
67 | MainWindow.xaml
68 | Code
69 |
70 |
71 |
72 |
73 | Code
74 |
75 |
76 | True
77 | True
78 | Resources.resx
79 |
80 |
81 | True
82 | Settings.settings
83 | True
84 |
85 |
86 | ResXFileCodeGenerator
87 | Resources.Designer.cs
88 |
89 |
90 | SettingsSingleFileGenerator
91 | Settings.Designer.cs
92 |
93 |
94 |
95 |
96 |
103 |
--------------------------------------------------------------------------------
/CaptureWindowDemo/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
25 |
31 |
32 |
33 |
34 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/CaptureWindowDemo/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Windows;
6 | using System.Windows.Controls;
7 | using System.Windows.Data;
8 | using System.Windows.Documents;
9 | using System.Windows.Input;
10 | using System.Windows.Media;
11 | using System.Windows.Media.Imaging;
12 | using System.Windows.Navigation;
13 | using System.Windows.Shapes;
14 |
15 | namespace CaptureWindowDemo
16 | {
17 | ///
18 | /// MainWindow.xaml 的交互逻辑
19 | ///
20 | public partial class MainWindow : Window
21 | {
22 | private IntPtr screenIntptr;
23 | private System.Drawing.Size screenSize;
24 |
25 | public MainWindow()
26 | {
27 | InitializeComponent();
28 |
29 | this.screenIntptr = CaptureWindowHelper.User32.GetDesktopWindow();
30 |
31 |
32 | CaptureWindowHelper.User32.RECT rect = new CaptureWindowHelper.User32.RECT();
33 |
34 | CaptureWindowHelper.User32.GetWindowRect(this.screenIntptr, ref rect);
35 |
36 | this.screenSize = new System.Drawing.Size(rect.right - rect.left, rect.bottom - rect.top);
37 | }
38 |
39 | private void captureFull_Click(object sender, RoutedEventArgs e)
40 | {
41 | var bitmap = CaptureWindowHelper.CaptureWindow(this.screenIntptr, this.screenSize.Width, this.screenSize.Height);
42 |
43 | if (bitmap == null)
44 | return;
45 |
46 | this.img.Source = this.BitmapToBitmapImage(bitmap);
47 | }
48 |
49 | private void captureThumbnail_Click(object sender, RoutedEventArgs e)
50 | {
51 | var bitmap = CaptureWindowHelper.CaptureWindow(this.screenIntptr, this.screenSize.Width, this.screenSize.Height, this.screenSize.Width / 2, this.screenSize.Height / 2);
52 |
53 | if (bitmap == null)
54 | return;
55 |
56 | this.img.Source = this.BitmapToBitmapImage(bitmap);
57 | }
58 |
59 |
60 | private BitmapImage BitmapToBitmapImage(System.Drawing.Bitmap bitmap)
61 | {
62 | BitmapImage bitmapImage = new BitmapImage();
63 |
64 | using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
65 | {
66 | bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
67 |
68 | bitmapImage.BeginInit();
69 | bitmapImage.StreamSource = ms;
70 | bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
71 | bitmapImage.EndInit();
72 | bitmapImage.Freeze();
73 | }
74 |
75 | // 释放资源
76 | bitmap.Dispose();
77 |
78 | return bitmapImage;
79 | }
80 |
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/CaptureWindowDemo/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // 有关程序集的一般信息由以下
8 | // 控制。更改这些特性值可修改
9 | // 与程序集关联的信息。
10 | [assembly: AssemblyTitle("CaptureWindowDemo")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("")]
14 | [assembly: AssemblyProduct("CaptureWindowDemo")]
15 | [assembly: AssemblyCopyright("Copyright © 2017")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | //将 ComVisible 设置为 false 将使此程序集中的类型
20 | //对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
21 | //请将此类型的 ComVisible 特性设置为 true。
22 | [assembly: ComVisible(false)]
23 |
24 | //若要开始生成可本地化的应用程序,请
25 | // 中的 .csproj 文件中
26 | //例如,如果您在源文件中使用的是美国英语,
27 | //使用的是美国英语,请将 设置为 en-US。 然后取消
28 | //对以下 NeutralResourceLanguage 特性的注释。 更新
29 | //以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //主题特定资源词典所处位置
36 | //(当资源未在页面
37 | //或应用程序资源字典中找到时使用)
38 | ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
39 | //(当资源未在页面
40 | //、应用程序或任何主题专用资源字典中找到时使用)
41 | )]
42 |
43 |
44 | // 程序集的版本信息由下列四个值组成:
45 | //
46 | // 主版本
47 | // 次版本
48 | // 生成号
49 | // 修订号
50 | //
51 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
52 | // 方法是按如下所示使用“*”: :
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.0.0.0")]
55 | [assembly: AssemblyFileVersion("1.0.0.0")]
56 |
--------------------------------------------------------------------------------
/CaptureWindowDemo/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本: 4.0.30319.42000
5 | //
6 | // 对此文件的更改可能导致不正确的行为,如果
7 | // 重新生成代码,则所做更改将丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace CaptureWindowDemo.Properties
12 | {
13 |
14 |
15 | ///
16 | /// 强类型资源类,用于查找本地化字符串等。
17 | ///
18 | // 此类是由 StronglyTypedResourceBuilder
19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
20 | // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen
21 | // (以 /str 作为命令选项),或重新生成 VS 项目。
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// 返回此类使用的缓存 ResourceManager 实例。
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CaptureWindowDemo.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// 覆盖当前线程的 CurrentUICulture 属性
56 | /// 使用此强类型的资源类的资源查找。
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/CaptureWindowDemo/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/CaptureWindowDemo/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace CaptureWindowDemo.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/CaptureWindowDemo/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/DropDownCustomColorPicker.Test/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/DropDownCustomColorPicker.Test/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Linq;
6 | using System.Windows;
7 |
8 | namespace DropDownCustomColorPicker.Test
9 | {
10 | ///
11 | /// App.xaml 的交互逻辑
12 | ///
13 | public partial class App : Application
14 | {
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/DropDownCustomColorPicker.Test/DropDownCustomColorPicker.Test.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {46B3AA45-E0B3-4D68-B91A-878D2DA7A0C9}
8 | WinExe
9 | Properties
10 | DropDownCustomColorPicker.Test
11 | DropDownCustomColorPicker.Test
12 | v4.0
13 | 512
14 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
15 | 4
16 |
17 |
18 | AnyCPU
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 |
27 |
28 | AnyCPU
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | 4.0
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | MSBuild:Compile
54 | Designer
55 |
56 |
57 | MSBuild:Compile
58 | Designer
59 |
60 |
61 | App.xaml
62 | Code
63 |
64 |
65 | MainWindow.xaml
66 | Code
67 |
68 |
69 |
70 |
71 | Code
72 |
73 |
74 | True
75 | True
76 | Resources.resx
77 |
78 |
79 | True
80 | Settings.settings
81 | True
82 |
83 |
84 | ResXFileCodeGenerator
85 | Resources.Designer.cs
86 |
87 |
88 | SettingsSingleFileGenerator
89 | Settings.Designer.cs
90 |
91 |
92 |
93 |
94 |
95 | {fd2ec7d4-4316-4f8f-8108-8381f0b4b340}
96 | DropDownCustomColorPicker
97 |
98 |
99 |
100 |
101 |
102 |
103 |
110 |
--------------------------------------------------------------------------------
/DropDownCustomColorPicker.Test/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/DropDownCustomColorPicker.Test/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Windows;
6 | using System.Windows.Controls;
7 | using System.Windows.Data;
8 | using System.Windows.Documents;
9 | using System.Windows.Input;
10 | using System.Windows.Media;
11 | using System.Windows.Media.Imaging;
12 | using System.Windows.Navigation;
13 | using System.Windows.Shapes;
14 |
15 | namespace DropDownCustomColorPicker.Test
16 | {
17 | ///
18 | /// MainWindow.xaml 的交互逻辑
19 | ///
20 | public partial class MainWindow : Window
21 | {
22 | public MainWindow()
23 | {
24 | InitializeComponent();
25 | this.Loaded += Window1_Loaded;
26 | }
27 |
28 | private void Window1_Loaded(object sender, RoutedEventArgs e)
29 | {
30 | this.customCP.SelectedColor = Colors.Green;
31 | }
32 |
33 | private void customCP_SelectedColorChanged(object sender, RoutedPropertyChangedEventArgs e)
34 | {
35 | this.canPreview.Background = new SolidColorBrush((Color)e.NewValue);
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/DropDownCustomColorPicker.Test/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // 有关程序集的一般信息由以下
8 | // 控制。更改这些特性值可修改
9 | // 与程序集关联的信息。
10 | [assembly: AssemblyTitle("DropDownCustomColorPicker.Test")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("")]
14 | [assembly: AssemblyProduct("DropDownCustomColorPicker.Test")]
15 | [assembly: AssemblyCopyright("Copyright © 2017")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | //将 ComVisible 设置为 false 将使此程序集中的类型
20 | //对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
21 | //请将此类型的 ComVisible 特性设置为 true。
22 | [assembly: ComVisible(false)]
23 |
24 | //若要开始生成可本地化的应用程序,请
25 | // 中的 .csproj 文件中
26 | //例如,如果您在源文件中使用的是美国英语,
27 | //使用的是美国英语,请将 设置为 en-US。 然后取消
28 | //对以下 NeutralResourceLanguage 特性的注释。 更新
29 | //以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //主题特定资源词典所处位置
36 | //(当资源未在页面
37 | //或应用程序资源字典中找到时使用)
38 | ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
39 | //(当资源未在页面
40 | //、应用程序或任何主题专用资源字典中找到时使用)
41 | )]
42 |
43 |
44 | // 程序集的版本信息由下列四个值组成:
45 | //
46 | // 主版本
47 | // 次版本
48 | // 生成号
49 | // 修订号
50 | //
51 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
52 | // 方法是按如下所示使用“*”: :
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.0.0.0")]
55 | [assembly: AssemblyFileVersion("1.0.0.0")]
56 |
--------------------------------------------------------------------------------
/DropDownCustomColorPicker.Test/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本: 4.0.30319.42000
5 | //
6 | // 对此文件的更改可能导致不正确的行为,如果
7 | // 重新生成代码,则所做更改将丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace DropDownCustomColorPicker.Test.Properties
12 | {
13 |
14 |
15 | ///
16 | /// 强类型资源类,用于查找本地化字符串等。
17 | ///
18 | // 此类是由 StronglyTypedResourceBuilder
19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
20 | // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen
21 | // (以 /str 作为命令选项),或重新生成 VS 项目。
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// 返回此类使用的缓存 ResourceManager 实例。
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DropDownCustomColorPicker.Test.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// 覆盖当前线程的 CurrentUICulture 属性
56 | /// 使用此强类型的资源类的资源查找。
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/DropDownCustomColorPicker.Test/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/DropDownCustomColorPicker.Test/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace DropDownCustomColorPicker.Test.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/DropDownCustomColorPicker.Test/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/DropDownCustomColorPicker.Test/readme.txt:
--------------------------------------------------------------------------------
1 | 该项目源自:
2 | http://wpfcolorpicker.codeplex.com/
3 | https://www.codeproject.com/Articles/42849/Making-a-Drop-Down-Style-Custom-Color-Picker-in-WP
4 |
5 | 但是,我已对源码做了大量修改,以适应自己的产品需求,也可以说是完善,也可以说是改进,当然也可能改“烂”了。
6 |
7 | 优化项:
8 | 1、预定义颜色的排序、视觉效果更美观
9 | 2、Expander 控件的自动折叠和展开、操作更方便。
10 |
11 | 3、优化使用鼠标选取像素点的操作,代码逻辑更简洁、操作更流畅。
12 | 4、增加了 SelectedColorChangedEvent 、 DropDownStateChangedEvent 事件
13 | 5、使用 Slider 替代了 TextBox 来修改 RGB 颜色值
14 |
15 | 6、增加了几个配置属性,使用起来更方便。
16 | 7、该项目会继续进行扩展及优化,敬请期待。
17 |
18 | 2017年5月13日
--------------------------------------------------------------------------------
/DropDownCustomColorPicker/ColorToSolidColorBrushConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Windows.Data;
6 | using System.Windows.Media;
7 |
8 | namespace DropDownCustomColorPicker
9 | {
10 |
11 | [ValueConversion(typeof(Color), typeof(Brush))]
12 | public class ColorToSolidColorBrushConverter : IValueConverter
13 | {
14 | #region IValueConverter Members
15 |
16 | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
17 | {
18 | return new SolidColorBrush((Color)value);
19 | }
20 |
21 | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
22 | {
23 | throw new NotImplementedException();
24 | }
25 |
26 | #endregion
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/DropDownCustomColorPicker/CustomColorPicker.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Windows;
5 | using System.Windows.Controls;
6 | using System.Windows.Data;
7 | using System.Windows.Documents;
8 | using System.Windows.Input;
9 | using System.Windows.Media;
10 | using System.Windows.Media.Imaging;
11 | using System.Windows.Navigation;
12 | using System.Windows.Shapes;
13 | using System.Windows.Controls.Primitives;
14 |
15 | namespace DropDownCustomColorPicker
16 | {
17 | ///
18 | /// Interaction logic for CustomColorPicker.xaml
19 | ///
20 | public partial class CustomColorPicker : UserControl
21 | {
22 |
23 | #region TBEvents
24 |
25 | ///
26 | /// 自定义颜色改变事件
27 | ///
28 | public static readonly RoutedEvent SelectedColorChangedEvent =
29 | EventManager.RegisterRoutedEvent("SelectedColorChanged", RoutingStrategy.Direct, typeof(RoutedPropertyChangedEventHandler), typeof(CustomColorPicker));
30 |
31 | ///
32 | /// 自定义颜色改变事件 CLR包装器
33 | ///
34 | public event RoutedPropertyChangedEventHandler SelectedColorChanged
35 | {
36 | add { this.AddHandler(SelectedColorChangedEvent, value); }
37 | remove { this.RemoveHandler(SelectedColorChangedEvent, value); }
38 | }
39 |
40 |
41 | ///
42 | /// 自定义DropDown状态改变事件
43 | ///
44 | public static readonly RoutedEvent DropDownStateChangedEvent =
45 | EventManager.RegisterRoutedEvent("DropDownStateChanged", RoutingStrategy.Direct, typeof(RoutedPropertyChangedEventHandler), typeof(CustomColorPicker));
46 |
47 | ///
48 | /// 自定义DropDown状态改变事件 CLR包装器
49 | ///
50 | public event RoutedPropertyChangedEventHandler DropDownStateChanged
51 | {
52 | add { this.AddHandler(DropDownStateChangedEvent, value); }
53 | remove { this.RemoveHandler(DropDownStateChangedEvent, value); }
54 | }
55 |
56 | #endregion
57 |
58 |
59 | #region DPProperties
60 |
61 | public Size ColorRectSize
62 | {
63 | get { return (Size)GetValue(ColorRectSizeProperty); }
64 | set { SetValue(ColorRectSizeProperty, value); }
65 | }
66 |
67 | public static readonly DependencyProperty ColorRectSizeProperty =
68 | DependencyProperty.Register("ColorRectSize", typeof(Size), typeof(CustomColorPicker), new PropertyMetadata(new Size(12, 12)));
69 |
70 |
71 | public PlacementMode Mode
72 | {
73 | get { return (PlacementMode)GetValue(ModeProperty); }
74 | set { SetValue(ModeProperty, value); }
75 | }
76 |
77 | public static readonly DependencyProperty ModeProperty =
78 | DependencyProperty.Register("Mode", typeof(PlacementMode), typeof(CustomColorPicker), new PropertyMetadata(PlacementMode.Bottom));
79 |
80 |
81 | #endregion
82 |
83 |
84 | public Color SelectedColor
85 | {
86 | get
87 | {
88 | return cp.CustomColor;
89 | }
90 | set
91 | {
92 | cp.CustomColor = value;
93 | recContent.Fill = new SolidColorBrush(value);
94 | }
95 | }
96 |
97 |
98 | public CustomColorPicker()
99 | {
100 | InitializeComponent();
101 |
102 | b.PreviewMouseLeftButtonUp += new MouseButtonEventHandler(b_PreviewMouseLeftButtonUp);
103 | }
104 |
105 |
106 | ///
107 | /// 打开Picker
108 | ///
109 | public void OpenPicker()
110 | {
111 | // 为快捷菜单设置焦点
112 | this.b.Focus();
113 |
114 | b_PreviewMouseLeftButtonUp(null, null);
115 | }
116 |
117 | ///
118 | /// 关闭 Picker
119 | ///
120 | public void ClosePicker()
121 | {
122 | if (b.ContextMenu != null)
123 | {
124 | b.ContextMenu.IsOpen = false;
125 | }
126 |
127 | // 转移焦点
128 | this.Focus();
129 | this.b.Focus();
130 | }
131 |
132 |
133 | #region Events
134 |
135 | internal void RaiseSelectedColorChangedEvent()
136 | {
137 | RoutedPropertyChangedEventArgs args = new RoutedPropertyChangedEventArgs(Colors.Transparent, cp.CustomColor, SelectedColorChangedEvent)
138 | {
139 | Source = this
140 | };
141 |
142 | recContent.Fill = new SolidColorBrush(cp.CustomColor);
143 | this.RaiseEvent(args);
144 | }
145 |
146 |
147 | protected void RaiseDropDownStateChangedEvent(bool opened)
148 | {
149 | RoutedPropertyChangedEventArgs args = new RoutedPropertyChangedEventArgs(false, opened, DropDownStateChangedEvent)
150 | {
151 | Source = this
152 | };
153 |
154 | this.RaiseEvent(args);
155 | }
156 |
157 | private void b_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
158 | {
159 | if (b.ContextMenu != null)
160 | {
161 | this.cp.CustomColorPicker = this;
162 | b.ContextMenu.PlacementTarget = b;
163 | b.ContextMenu.Placement = this.Mode;
164 | ContextMenuService.SetPlacement(b, this.Mode);
165 | b.ContextMenu.IsOpen = true;
166 | }
167 | }
168 |
169 | private void ContextMenu_Closed(object sender, RoutedEventArgs e)
170 | {
171 | RaiseDropDownStateChangedEvent(false);
172 | }
173 |
174 | private void ContextMenu_Opened(object sender, RoutedEventArgs e)
175 | {
176 | RaiseDropDownStateChangedEvent(true);
177 | }
178 |
179 | #endregion
180 |
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/DropDownCustomColorPicker/CustomColors.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using System.Text;
6 | using System.Windows.Media;
7 |
8 | namespace DropDownCustomColorPicker
9 | {
10 | ///
11 | /// 反射预定义颜色
12 | ///
13 | public class CustomColors
14 | {
15 | List selectableColors = null;
16 |
17 | public List SelectableColors
18 | {
19 | get { return selectableColors; }
20 | set { selectableColors = value; }
21 | }
22 |
23 | public CustomColors()
24 | {
25 | var list = new List();
26 |
27 | Type ColorsType = typeof(Colors);
28 | PropertyInfo[] ColorsProperty = ColorsType.GetProperties();
29 |
30 | foreach (PropertyInfo property in ColorsProperty)
31 | {
32 | list.Add((Color)ColorConverter.ConvertFromString(property.Name));
33 | }
34 |
35 | list.Sort(new Comparison((Color x, Color y) =>
36 | {
37 | var xtotal = x.R + x.G + x.B;
38 |
39 | var ytotal = y.R + y.G + y.B;
40 |
41 | return xtotal.CompareTo(ytotal); // 升序排列
42 | }));
43 |
44 | selectableColors = list;
45 | }
46 |
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/DropDownCustomColorPicker/DropDownCustomColorPicker.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {FD2EC7D4-4316-4F8F-8108-8381F0B4B340}
7 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
8 | DropDownCustomColorPicker
9 | DropDownCustomColorPicker
10 | 4
11 | Library
12 | 3.0
13 | false
14 | v4.0
15 |
16 |
17 |
18 |
19 | 3.5
20 |
21 |
22 |
23 | Publish\
24 | true
25 | Web
26 | true
27 | Foreground
28 | 7
29 | Days
30 | false
31 | false
32 | true
33 | 0
34 | 1.0.0.%2a
35 | false
36 | true
37 |
38 |
39 | true
40 | full
41 | false
42 | .\bin\Debug\
43 | DEBUG;TRACE
44 | false
45 |
46 |
47 | false
48 | true
49 | .\bin\Release\
50 | TRACE
51 | false
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | 3.0
63 |
64 |
65 | 3.0
66 |
67 |
68 | 3.0
69 |
70 |
71 | 3.0
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | Designer
80 | MSBuild:Compile
81 |
82 |
83 | MSBuild:Compile
84 | Designer
85 |
86 |
87 |
88 |
89 |
90 | CustomColorPicker.xaml
91 |
92 |
93 | ColorPicker.xaml
94 |
95 |
96 |
97 |
98 | ResXFileCodeGenerator
99 | Designer
100 | Resources.Designer.cs
101 |
102 |
103 | SettingsSingleFileGenerator
104 | Settings.Designer.cs
105 |
106 |
107 | True
108 | True
109 | Resources.resx
110 |
111 |
112 | True
113 | True
114 | Settings.settings
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 | False
124 | .NET Framework 3.5 SP1
125 | true
126 |
127 |
128 |
129 |
130 |
131 |
132 |
--------------------------------------------------------------------------------
/DropDownCustomColorPicker/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | #region Using directives
2 |
3 | using System.Reflection;
4 | using System.Runtime.CompilerServices;
5 | using System.Resources;
6 | using System.Globalization;
7 | using System.Windows;
8 | using System.Runtime.InteropServices;
9 |
10 | #endregion
11 |
12 | // General Information about an assembly is controlled through the following
13 | // set of attributes. Change these attribute values to modify the information
14 | // associated with an assembly.
15 | [assembly: AssemblyTitle("WindowsApplication1")]
16 | [assembly: AssemblyDescription("")]
17 | [assembly: AssemblyConfiguration("")]
18 | [assembly: AssemblyCompany("")]
19 | [assembly: AssemblyProduct("WindowsApplication1")]
20 | [assembly: AssemblyCopyright("Copyright @ 2006")]
21 | [assembly: AssemblyTrademark("")]
22 | [assembly: AssemblyCulture("")]
23 | [assembly: ComVisible(false)]
24 |
25 | //In order to begin building localizable applications, set
26 | //CultureYouAreCodingWith in your .csproj file
27 | //inside a . For example, if you are using US english
28 | //in your source files, set the to en-US. Then uncomment
29 | //the NeutralResourceLanguage attribute below. Update the "en-US" in
30 | //the line below to match the UICulture setting in the project file.
31 |
32 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
33 |
34 |
35 | [assembly: ThemeInfo(
36 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
37 | //(used if a resource is not found in the page,
38 | // or application resource dictionaries)
39 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
40 | //(used if a resource is not found in the page,
41 | // app, or any theme specific resource dictionaries)
42 | )]
43 |
44 |
45 | // Version information for an assembly consists of the following four values:
46 | //
47 | // Major Version
48 | // Minor Version
49 | // Build Number
50 | // Revision
51 | //
52 | // You can specify all the values or you can default the Revision and Build Numbers
53 | // by using the '*' as shown below:
54 | [assembly: AssemblyVersion("1.0.*")]
55 |
--------------------------------------------------------------------------------
/DropDownCustomColorPicker/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本:4.0.30319.42000
5 | //
6 | // 对此文件的更改可能会导致不正确的行为,并且如果
7 | // 重新生成代码,这些更改将会丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace DropDownCustomColorPicker.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// 一个强类型的资源类,用于查找本地化的字符串等。
17 | ///
18 | // 此类是由 StronglyTypedResourceBuilder
19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
21 | // (以 /str 作为命令选项),或重新生成 VS 项目。
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// 返回此类使用的缓存的 ResourceManager 实例。
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DropDownCustomColorPicker.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// 使用此强类型资源类,为所有资源查找
51 | /// 重写当前线程的 CurrentUICulture 属性。
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// 查找 System.Drawing.Bitmap 类型的本地化资源。
65 | ///
66 | internal static System.Drawing.Bitmap ColorSwatchCircle {
67 | get {
68 | object obj = ResourceManager.GetObject("ColorSwatchCircle", resourceCulture);
69 | return ((System.Drawing.Bitmap)(obj));
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/DropDownCustomColorPicker/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | ..\Resources\image.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
123 |
124 |
--------------------------------------------------------------------------------
/DropDownCustomColorPicker/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本:4.0.30319.42000
5 | //
6 | // 对此文件的更改可能会导致不正确的行为,并且如果
7 | // 重新生成代码,这些更改将会丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace DropDownCustomColorPicker.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/DropDownCustomColorPicker/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/DropDownCustomColorPicker/Resources/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iqingyu/BlogsDemo/8401c5b8646fcd8700ae2e068e581cecdbec1238/DropDownCustomColorPicker/Resources/image.png
--------------------------------------------------------------------------------
/DropDownCustomColorPicker/readme.txt:
--------------------------------------------------------------------------------
1 | 该项目源自:
2 | http://wpfcolorpicker.codeplex.com/
3 | https://www.codeproject.com/Articles/42849/Making-a-Drop-Down-Style-Custom-Color-Picker-in-WP
4 |
5 | 但是,我已对源码做了大量修改,以适应自己的产品需求,也可以说是完善,也可以说是改进,当然也可能改“烂”了。
6 |
7 | 2017年4月26日
--------------------------------------------------------------------------------
/ParallelDemo/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/ParallelDemo/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/ParallelDemo/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 |
9 | namespace ParallelDemo
10 | {
11 | ///
12 | /// App.xaml 的交互逻辑
13 | ///
14 | public partial class App : Application
15 | {
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/ParallelDemo/Demo/AbstractClass.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows.Controls;
7 | using ParallelDemo;
8 | using System.Threading;
9 |
10 | namespace ParallelDemo.Demo
11 | {
12 | public abstract class AbstractClass
13 | {
14 | protected static string TXT_NAME = "txtTip";
15 | protected IView view;
16 |
17 | public AbstractClass(IView view)
18 | {
19 | this.view = view;
20 | }
21 |
22 | protected void PrintInfo(string tip)
23 | {
24 | this.view.DispatcherAction(() =>
25 | {
26 | TextBox txtTip = this.view.GetObjectByName(TXT_NAME) as TextBox;
27 | txtTip.PrintInfo(tip);
28 | });
29 | }
30 |
31 | protected void PrintExInfo(Exception ex)
32 | {
33 | this.view.DispatcherAction(() =>
34 | {
35 | TextBox txtTip = this.view.GetObjectByName(TXT_NAME) as TextBox;
36 | txtTip.PrintInfo($"Exception.Message: {ex.Message}");
37 | });
38 | }
39 |
40 | public void PrintThreadInfo(string tag, string args)
41 | {
42 | PrintInfo($"Tag:{tag}, Args:{args}, ManagedThreadId:{Thread.CurrentThread.ManagedThreadId}");
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/ParallelDemo/Demo/AtomicityClass.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 |
8 | namespace ParallelDemo.Demo
9 | {
10 | public class AtomicityClass : AbstractClass
11 | {
12 | public AtomicityClass(IView view) : base(view)
13 | {
14 | }
15 |
16 | ///
17 | /// 测试原子性
18 | ///
19 | public void TestAtomicity()
20 | {
21 | long test = 0;
22 |
23 | long breakFlag = 0;
24 | int index = 0;
25 | Task.Run(() =>
26 | {
27 | base.PrintInfo("开始循环 写数据");
28 | while (true)
29 | {
30 | test = (index % 2 == 0) ? 0x0 : 0x1234567890abcdef;
31 |
32 | index++;
33 |
34 | if (Interlocked.Read(ref breakFlag) > 0)
35 | {
36 | break;
37 | }
38 | }
39 |
40 | base.PrintInfo("退出循环 写数据");
41 | });
42 |
43 | Task.Run(() =>
44 | {
45 | base.PrintInfo("开始循环 读数据");
46 | while (true)
47 | {
48 | long temp = test;
49 |
50 | if (temp != 0 && temp != 0x1234567890abcdef)
51 | {
52 | Interlocked.Increment(ref breakFlag);
53 | base.PrintInfo($"读写撕裂: { Convert.ToString(temp, 16)}");
54 | break;
55 | }
56 | }
57 |
58 | base.PrintInfo("退出循环 读数据");
59 | });
60 | }
61 |
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/ParallelDemo/Demo/AwaitAsyncClass.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace ParallelDemo.Demo
9 | {
10 | public class AwaitAsyncClass : AbstractClass
11 | {
12 | public AwaitAsyncClass(IView view) : base(view)
13 | {
14 |
15 | }
16 |
17 | ///
18 | /// 第一个简单demo
19 | ///
20 | ///
21 | public async Task MethodAsync()
22 | {
23 | PrintInfo($"ManagedThreadId - 1 - :{Thread.CurrentThread.ManagedThreadId}");
24 |
25 | // 休眠
26 | await Task.Delay(TimeSpan.FromMilliseconds(100));
27 |
28 | PrintInfo($"ManagedThreadId - 2 - :{Thread.CurrentThread.ManagedThreadId}");
29 | }
30 |
31 | ///
32 | /// 在循环中使用await, 观察使用的线程数量
33 | ///
34 | ///
35 | public async Task ForMethodAsync()
36 | {
37 | // 休眠
38 | // await Task.Delay(TimeSpan.FromMilliseconds(100)).ConfigureAwait(false);
39 |
40 | for (int i = 0; i < 5; i++)
41 | {
42 | await Task.Run(() =>
43 | {
44 | // 打印线程id
45 | PrintThreadInfo("ForMethodAsync", i.ToString());
46 | });
47 | }
48 | }
49 |
50 |
51 | ///
52 | /// 死锁 Demo
53 | ///
54 | ///
55 | public async Task DeadLockDemoAsync()
56 | {
57 | await Task.Delay(TimeSpan.FromMilliseconds(100));// deadlock
58 |
59 | //await Task.Delay(TimeSpan.FromMilliseconds(100)).ConfigureAwait(false);// un-deadlock
60 |
61 | DeadlockDemo.Test();
62 | }
63 |
64 | }
65 |
66 | ///
67 | /// MSDN Demo
68 | ///
69 | public static class DeadlockDemo
70 | {
71 | private static async Task DelayAsync()
72 | {
73 | await Task.Delay(1000);
74 | }
75 | // This method causes a deadlock when called in a GUI or ASP.NET context.
76 | public static void Test()
77 | {
78 | // Start the delay.
79 | var delayTask = DelayAsync();
80 | // Wait for the delay to complete.
81 | delayTask.Wait();
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/ParallelDemo/Demo/ConcurrentCollectionClass.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 |
9 | namespace ParallelDemo.Demo
10 | {
11 | public class ConcurrentCollectionClass : AbstractClass
12 | {
13 | public ConcurrentCollectionClass(IView view) : base(view)
14 | {
15 | }
16 |
17 |
18 | ///
19 | /// MSDN Demo
20 | /// BlockingCollection.Add()
21 | /// BlockingCollection.CompleteAdding()
22 | /// BlockingCollection.TryTake()
23 | /// BlockingCollection.IsCompleted
24 | ///
25 | public void Demo1()
26 | {
27 | // Construct and fill our BlockingCollection
28 | using (BlockingCollection blocking = new BlockingCollection())
29 | {
30 | int NUMITEMS = 10000;
31 |
32 | for (int i = 0; i < NUMITEMS; i++)
33 | {
34 | blocking.Add(i);
35 | }
36 | blocking.CompleteAdding();
37 |
38 |
39 | int outerSum = 0;
40 |
41 | // Delegate for consuming the BlockingCollection and adding up all items
42 | Action action = () =>
43 | {
44 | int localItem;
45 | int localSum = 0;
46 |
47 | while (blocking.TryTake(out localItem))
48 | {
49 | localSum += localItem;
50 | }
51 | Interlocked.Add(ref outerSum, localSum);
52 | };
53 |
54 | // Launch three parallel actions to consume the BlockingCollection
55 | Parallel.Invoke(action, action, action);
56 |
57 | base.PrintInfo(string.Format("Sum[0..{0}) = {1}, should be {2}", NUMITEMS, outerSum, ((NUMITEMS * (NUMITEMS - 1)) / 2)));
58 | base.PrintInfo(string.Format("bc.IsCompleted = {0} (should be true)", blocking.IsCompleted));
59 |
60 | }
61 | }
62 |
63 |
64 | ///
65 | /// 限制容量
66 | ///
67 | public void Demo2()
68 | {
69 | BlockingCollection blocking = new BlockingCollection(5);
70 |
71 | Task.Run(() =>
72 | {
73 | for (int i = 0; i < 20; i++)
74 | {
75 | blocking.Add(i);
76 | PrintInfo($"add:({i})");
77 | }
78 |
79 | blocking.CompleteAdding();
80 | PrintInfo("CompleteAdding");
81 | });
82 |
83 | // 等待先生产数据
84 | Task.Delay(500).ContinueWith((t) =>
85 | {
86 | while (!blocking.IsCompleted)
87 | {
88 | var n = 0;
89 | if (blocking.TryTake(out n))
90 | {
91 | PrintInfo($"TryTake:({n})");
92 | }
93 | }
94 |
95 | PrintInfo("IsCompleted = true");
96 | });
97 |
98 | }
99 |
100 |
101 | ///
102 | /// 在 BlockingCollection 中使用Stack
103 | ///
104 | public void Demo3()
105 | {
106 | BlockingCollection blocking = new BlockingCollection(new ConcurrentStack(), 5);
107 |
108 | Task.Run(() =>
109 | {
110 | for (int i = 0; i < 20; i++)
111 | {
112 | blocking.Add(i);
113 | PrintInfo($"add:({i})");
114 | }
115 |
116 | blocking.CompleteAdding();
117 | PrintInfo("CompleteAdding");
118 | });
119 |
120 | // 等待先生产数据
121 | Task.Delay(500).ContinueWith((t) =>
122 | {
123 | while (!blocking.IsCompleted)
124 | {
125 | var n = 0;
126 | if (blocking.TryTake(out n))
127 | {
128 | PrintInfo($"TryTake:({n})");
129 | }
130 | }
131 |
132 | PrintInfo("IsCompleted = true");
133 | });
134 |
135 |
136 |
137 | }
138 |
139 |
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/ParallelDemo/Demo/InterlockedSpinLockClass.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.Concurrent;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 |
9 | namespace ParallelDemo.Demo
10 | {
11 | ///
12 | /// 原子操作和自旋锁Demo
13 | ///
14 | public class InterlockedSpinLockClass : AbstractClass
15 | {
16 | public InterlockedSpinLockClass(IView view) : base(view)
17 | {
18 | }
19 |
20 | ///
21 | /// 原子操作-计数
22 | ///
23 | public void Demo1()
24 | {
25 | Task.Run(() =>
26 | {
27 | long total = 0;
28 | long result = 0;
29 |
30 | PrintInfo("正在计数");
31 |
32 | Parallel.For(0, 10, (i) =>
33 | {
34 | for (int j = 0; j < 10000000; j++)
35 | {
36 | Interlocked.Increment(ref total);
37 | result++;
38 | }
39 | });
40 |
41 | PrintInfo($"操作结果应该为\t\t: {10 * 10000000}");
42 | PrintInfo($"原子操作结果\t\t: {total}");
43 | PrintInfo($"i++操作结果\t\t: {result}");
44 | });
45 | }
46 |
47 | ///
48 | /// 原子操作-单例模式
49 | ///
50 | public void Demo2()
51 | {
52 | ConcurrentQueue queue = new ConcurrentQueue();
53 |
54 | // 虽然这个测试不严谨、但也或多或少的说明了一些问题
55 | for (int i = 0; i < 10; i++) // 同时分配的线程数过多、调度器反而调度不过来
56 | {
57 | Task.Run(() =>
58 | {
59 | var result = InterlockedSingleClass.SingleInstance;
60 |
61 | queue.Enqueue(result);
62 | });
63 | }
64 |
65 |
66 | // 1秒钟后显示结果
67 | Task.Delay(1000).ContinueWith((t) =>
68 | {
69 | PrintInfo($"利用原子操作-单例模式、生成的对象总数:{queue.Count}");
70 |
71 | InterlockedSingleClass firstItem = null;
72 | queue.TryDequeue(out firstItem);
73 |
74 | for (int i = 0; i < queue.Count;)
75 | {
76 | InterlockedSingleClass temp = null;
77 | queue.TryDequeue(out temp);
78 |
79 | if (temp == null || firstItem == null || !object.ReferenceEquals(temp, firstItem))
80 | {
81 | PrintInfo("单例模式失效(按照预期、该代码不会被运行到)");
82 | }
83 | }
84 |
85 | PrintInfo("原子操作-单例模式-运行完毕");
86 | });
87 |
88 | }
89 |
90 |
91 | ///
92 | /// 自旋锁Demo,来源MSDN
93 | ///
94 | public void Demo3()
95 | {
96 | SpinLock sl = new SpinLock();
97 |
98 | StringBuilder sb = new StringBuilder();
99 |
100 | // Action taken by each parallel job.
101 | // Append to the StringBuilder 10000 times, protecting
102 | // access to sb with a SpinLock.
103 | Action action = () =>
104 | {
105 | bool gotLock = false;
106 | for (int i = 0; i < 10000; i++)
107 | {
108 | gotLock = false;
109 | try
110 | {
111 | sl.Enter(ref gotLock);
112 |
113 | sb.Append((i % 10).ToString());
114 | }
115 | finally
116 | {
117 | // Only give up the lock if you actually acquired it
118 | if (gotLock)
119 | sl.Exit();
120 | }
121 | }
122 | };
123 |
124 | // Invoke 3 concurrent instances of the action above
125 | Parallel.Invoke(action, action, action);
126 |
127 | // Check/Show the results
128 | PrintInfo($"sb.Length = {sb.Length} (should be 30000)");
129 |
130 | PrintInfo($"number of occurrences of '5' in sb: {sb.ToString().Where(c => (c == '5')).Count()} (should be 3000)");
131 |
132 | }
133 |
134 |
135 |
136 | public class InterlockedSingleClass
137 | {
138 | private static InterlockedSingleClass single = null;
139 |
140 | public static InterlockedSingleClass SingleInstance
141 | {
142 | get
143 | {
144 | // if (single == null) // 为了测试效果,该行代码注释掉
145 | {
146 | Interlocked.CompareExchange(ref single, new InterlockedSingleClass(), null);
147 | }
148 |
149 | return single;
150 | }
151 | }
152 |
153 | }
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/ParallelDemo/Demo/LockMonitorClass.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 |
8 | namespace ParallelDemo.Demo
9 | {
10 | public class LockMonitorClass : AbstractClass
11 | {
12 | public LockMonitorClass(IView view) : base(view)
13 | {
14 | }
15 |
16 | public object thisLock = new object();
17 | private long index;
18 |
19 | public void AddIndex()
20 | {
21 | lock (this.thisLock)
22 | {
23 | this.index++;
24 |
25 | if (this.index > long.MaxValue / 2)
26 | {
27 | this.index = 0;
28 | }
29 | // 和 index 无关的大量操作
30 | }
31 | }
32 |
33 | public long GetIndex()
34 | {
35 | return this.index;
36 | }
37 |
38 |
39 |
40 |
41 |
42 | public class BankAccount
43 | {
44 | private long id;
45 | private decimal m_balance = 0.0M;
46 |
47 | private object m_balanceLock = new object();
48 |
49 | public void Deposit(decimal delta)
50 | {
51 | lock (m_balanceLock)
52 | {
53 | m_balance += delta;
54 | }
55 | }
56 |
57 | public void Withdraw(decimal delta)
58 | {
59 | lock (m_balanceLock)
60 | {
61 | if (m_balance < delta)
62 | throw new Exception("Insufficient funds");
63 | m_balance -= delta;
64 | }
65 | }
66 |
67 | public static void ErrorTransfer(BankAccount a, BankAccount b, decimal delta)
68 | {
69 | a.Withdraw(delta);
70 | b.Deposit(delta);
71 | }
72 |
73 |
74 | public static void Transfer(BankAccount a, BankAccount b, decimal delta)
75 | {
76 | lock (a.m_balanceLock)
77 | {
78 | lock (b.m_balanceLock)
79 | {
80 | a.Withdraw(delta);
81 | b.Deposit(delta);
82 | }
83 | }
84 | }
85 |
86 | public static void RightTransfer(BankAccount a, BankAccount b, decimal delta)
87 | {
88 | if (a.id < b.id)
89 | {
90 | Monitor.Enter(a.m_balanceLock); // A first
91 | Monitor.Enter(b.m_balanceLock); // ...and then B
92 | }
93 | else
94 | {
95 | Monitor.Enter(b.m_balanceLock); // B first
96 | Monitor.Enter(a.m_balanceLock); // ...and then A
97 | }
98 |
99 | try
100 | {
101 | a.Withdraw(delta);
102 | b.Deposit(delta);
103 | }
104 | finally
105 | {
106 | Monitor.Exit(a.m_balanceLock);
107 | Monitor.Exit(b.m_balanceLock);
108 | }
109 | }
110 |
111 | }
112 |
113 |
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/ParallelDemo/Demo/PLinqClass.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 | using System.Windows.Controls;
8 |
9 | namespace ParallelDemo.Demo
10 | {
11 | ///
12 | /// Linq 的 并行版本
13 | ///
14 | public class PLinqClass : AbstractClass
15 | {
16 | public PLinqClass(IView view) : base(view)
17 | {
18 |
19 | }
20 |
21 | ///
22 | /// PLinq:Linq的并行版本
23 | ///
24 | public void Demo1()
25 | {
26 | Task.Run(() =>
27 | {
28 | var result = Enumerable.Range(1, 10).AsParallel().Where(e =>
29 | {
30 | PrintInfo("开始 " + e);
31 |
32 | PrintInfo("休眠 " + e);
33 | Thread.Sleep(1000);
34 |
35 | PrintInfo("结束 " + e);
36 | return e > 5;
37 | });
38 |
39 | PrintInfo("打印结果");
40 |
41 | foreach (var item in result)
42 | {
43 | PrintInfo(item.ToString());
44 | }
45 |
46 | PrintInfo("并行查询执行完毕");
47 | });
48 | }
49 |
50 |
51 | ///
52 | /// PLinq:按顺序输出结果
53 | ///
54 | public void Demo2()
55 | {
56 | Task.Run(() =>
57 | {
58 | var result = Enumerable.Range(1, 10).AsParallel().AsOrdered().Where(e =>
59 | {
60 | PrintInfo("开始 " + e);
61 |
62 | PrintInfo("休眠 " + e);
63 | Thread.Sleep(1000);
64 |
65 | PrintInfo("结束 " + e);
66 | return e > 5;
67 | });
68 |
69 | PrintInfo("打印结果");
70 |
71 | foreach (var item in result)
72 | {
73 | PrintInfo(item.ToString());
74 | }
75 |
76 | PrintInfo("并行查询执行完毕");
77 | });
78 | }
79 |
80 |
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/ParallelDemo/Demo/ParallelClass.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Threading;
7 | using System.Windows.Controls;
8 |
9 | namespace ParallelDemo.Demo
10 | {
11 | public class ParallelClass : AbstractClass
12 | {
13 | public ParallelClass(IView view) : base(view)
14 | {
15 | }
16 |
17 | ///
18 | /// Parallel.Invoke并行多个独立的Action
19 | ///
20 | public void Demo1()
21 | {
22 | Task.Run(() =>
23 | {
24 | List actions = new List();
25 |
26 | // 生成并行任务
27 | for (int i = 0; i < 5; i++)
28 | {
29 | // 注意、这里很关键,不可直接使用i变量。
30 | // 原因在稍后的随笔中进行说明
31 | int index = i;
32 | actions.Add(new Action(() =>
33 | {
34 | PrintInfo(string.Format("Task{0} 开始", index));
35 |
36 | PrintInfo(string.Format("Task{0} 休眠1秒", index));
37 | Thread.Sleep(1000);
38 |
39 |
40 | PrintInfo(string.Format("Task{0} 休眠5秒", index));
41 | Thread.Sleep(5000);
42 |
43 | PrintInfo(string.Format("Task{0} 结束", index));
44 | }));
45 | }
46 |
47 | // 执行并行任务
48 | Parallel.Invoke(actions.ToArray());
49 |
50 | // 当上述的5个任务全部执行完毕后,才会执行该代码
51 | PrintInfo("并行任务执行完毕");
52 | });
53 | }
54 |
55 |
56 | ///
57 | /// Parallel简单的For并行
58 | ///
59 | public void Demo2()
60 | {
61 | // 为了实时更新UI、将代码异步执行
62 | Task.Run(() =>
63 | {
64 | Parallel.For(1, 100, (index) =>
65 | {
66 | PrintInfo(string.Format("Index:{0}, 开始执行Task", index));
67 |
68 | Thread.Sleep(1000);
69 | PrintInfo(string.Format("Index:{0}, 开始休眠Action 1秒", index));
70 |
71 | PrintInfo(string.Format("Index:{0}, Task执行完毕", index));
72 | });
73 |
74 | PrintInfo("并行任务执行完毕");
75 | });
76 | }
77 |
78 | ///
79 | /// 中断Parallel.For并行
80 | ///
81 | public void Demo3()
82 | {
83 | // 为了实时更新UI、将代码异步执行
84 | Task.Run(() =>
85 | {
86 | int breakIndex = new Random().Next(10, 50);
87 | PrintInfo(" BreakIndex : -------------------------" + breakIndex);
88 |
89 | Parallel.For(1, 100, (index, state) =>
90 | {
91 | PrintInfo(string.Format("Index:{0}, 开始执行Task", index));
92 |
93 | if (breakIndex == index)
94 | {
95 | PrintInfo(string.Format("Index:{0}, ------------------ Break Task", index));
96 | state.Break();
97 | // Break方法执行后、
98 | // 大于 当前索引的并且未被安排执行的迭代将被放弃
99 | // 小于 当前索引的的迭代将继续正常执行直至迭代执行完毕
100 | return;
101 | }
102 |
103 | Thread.Sleep(1000);
104 | PrintInfo(string.Format("Index:{0}, 休眠Action 1秒", index));
105 |
106 | PrintInfo(string.Format("Index:{0}, Task执行完毕", index));
107 | });
108 |
109 | PrintInfo("并行任务执行完毕");
110 | });
111 | }
112 |
113 |
114 | ///
115 | /// 终止Parallel.For并行
116 | ///
117 | public void Demo4()
118 | {
119 | // 为了实时更新UI、将代码异步执行
120 | Task.Run(() =>
121 | {
122 | int stopIndex = new Random().Next(10, 50);
123 | PrintInfo(" StopIndex : -------------------------" + stopIndex);
124 |
125 | Parallel.For(1, 100, (index, state) =>
126 | {
127 | PrintInfo(string.Format("Index:{0}, 开始执行Task", index));
128 |
129 | if (stopIndex == index)
130 | {
131 | PrintInfo(string.Format("Index:{0}, ------------------ Stop Task", index));
132 | state.Stop();
133 | // Stop方法执行后
134 | // 整个迭代将被放弃
135 | return;
136 | }
137 |
138 | Thread.Sleep(1000);
139 | PrintInfo(string.Format("Index:{0}, 休眠Action 1秒", index));
140 |
141 | PrintInfo(string.Format("Index:{0}, Task执行完毕", index));
142 | });
143 |
144 | PrintInfo("并行任务执行完毕");
145 | });
146 | }
147 |
148 |
149 | ///
150 | /// Parallel.For并行中的数据聚合
151 | ///
152 | public void Demo5()
153 | {
154 | Task.Run(() =>
155 | {
156 | // 求 1 到 10 的阶乘的 和
157 | long total = 0;
158 | Parallel.For(1, 10,
159 | () =>
160 | {
161 | PrintInfo("LocalInit");
162 | return 0;
163 | },
164 | (index, state, local) =>
165 | {
166 | PrintInfo("Body");
167 | int result = 1;
168 | for (int i = 2; i < index; i++)
169 | {
170 | result *= i;
171 | }
172 | local += result;
173 | return local;
174 | },
175 | (x) =>
176 | {
177 | PrintInfo("LocalFinally");
178 | Interlocked.Add(ref total, x);
179 | });
180 |
181 | PrintInfo("Total : " + total);
182 | PrintInfo("并行任务执行完毕");
183 | });
184 |
185 |
186 | // MSDN备注:
187 | // 对于参与循环执行的每个线程调用 LocalInit 委托一次,并返回每个线程的初始本地状态。
188 | // 这些初始状态传递到每个线程上的第一个 body 调用。 然后,每个后续正文调用返回可能修改过的状态值,传递到下一个正文调用。
189 | // 最后,每个线程上的最后正文调用返回传递给 LocalFinally 委托的状态值。
190 | // 每个线程调用 localFinally 委托一次,以对每个线程的本地状态执行最终操作。
191 | // 此委托可以被多个线程同步调用;因此您必须同步对任何共享变量的访问。
192 |
193 | // 也就是说:
194 | // 1) 并行中开辟的线程数 决定了 LocalInit、LocalFinally 的调用次数
195 | // 2) 多个 迭代委托、Body 可能被同一个线程调用。
196 | // 3) 迭代委托、Body 中的 local值,并不一定是 LocalInit 的初始值,也有可能是被修改的返回值。
197 | // 4) LocalFinally 可能是被同时调用的,需要注意线程同步问题。
198 | }
199 |
200 |
201 | ///
202 | /// Parallel.ForEach并行
203 | ///
204 | public void Demo6()
205 | {
206 | Task.Run(() =>
207 | {
208 | Parallel.ForEach(Enumerable.Range(1, 10), (num) =>
209 | {
210 | PrintInfo("Task 开始");
211 |
212 |
213 | PrintInfo("Task 休眠" + num + "秒");
214 | Thread.Sleep(TimeSpan.FromSeconds(num));
215 |
216 |
217 | PrintInfo("Task 结束");
218 | });
219 |
220 | PrintInfo("并行任务执行完毕");
221 | });
222 | }
223 |
224 | ///
225 | /// Parallel.ForEach中的索引,中断、终止操作
226 | ///
227 | public void Demo7()
228 | {
229 | Task.Run(() =>
230 | {
231 | Parallel.ForEach(Enumerable.Range(0, 10), (num, state, index) =>
232 | {
233 | // num, 并行数据源中的数据项
234 | // state,
235 | PrintInfo(" Index : " + index + " Num: " + num);
236 | });
237 | PrintInfo("并行任务执行完毕");
238 | });
239 | }
240 |
241 |
242 |
243 | }
244 | }
245 |
--------------------------------------------------------------------------------
/ParallelDemo/Demo/TaskClass.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Net;
5 | using System.Text;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 | using System.Windows.Controls;
9 |
10 | namespace ParallelDemo.Demo
11 | {
12 | public class TaskClass : AbstractClass
13 | {
14 | public TaskClass(IView view) : base(view)
15 | {
16 | }
17 |
18 |
19 | ///
20 | /// Task.NET 4.0 中提倡的方式
21 | ///
22 | ///
23 | public void Demo1()
24 | {
25 | // Task 对外公开了构造函数、但是微软并不建议直接使用Task构造函数去实例化对象,而是 使用 Task.Factory.StartNew();
26 |
27 | // MSDN 中的备注如下:
28 | // For performance reasons, TaskFactory's StartNew method should be the preferred mechanism for creating and scheduling computational tasks,
29 | // but for scenarios where creation and scheduling must be separated, the constructors may be used,
30 | // and the task's Start method may then be used to schedule the task for execution at a later time.
31 | // Task 类还提供了初始化任务但不计划执行任务的构造函数。 出于性能方面的考虑,TaskFactory 的 StartNew 方法应该是创建和计划计算任务的首选机制,
32 | // 但是对于创建和计划必须分开的情况,可以使用构造函数,然后可以使用任务的 Start 方法计划任务在稍后执行。
33 |
34 |
35 | Task.Factory.StartNew(() =>
36 | {
37 | base.PrintInfo("Task.Factory.StartNew(一个参数)");
38 | }).ContinueWith((t) =>
39 | {
40 | base.PrintInfo(t.Id.ToString());
41 | base.PrintInfo(t.CreationOptions.ToString());
42 | }).ContinueWith((t) =>
43 | {
44 | base.PrintInfo(t.Id.ToString());
45 | base.PrintInfo(t.CreationOptions.ToString());
46 | });
47 |
48 | // Task.Factory.StartNew 提供了高达16个的重载函数。
49 | // 其中 Task.Factory.StartNew 是创建带有返回值的异步任务。
50 |
51 | // 以最复杂的重载为例、逐一介绍其参数
52 | // public Task StartNew(Func