Universal Windows Platform (UWP) 和 Windows Presentation Foundation (WPF) 是不相同的,虽然都可以做界面,但是 UWP 是一个新的 UI 框架,而且 UWP 是支持很多平台,至少比 WPF 多。
那么UWP 可以使用什么写?
WPF 可以使用 xaml 做的前台,C#、VB、F#、C++写的后台。
不过需要知道,WPF 的C++ 后台使用的是托管的C++。
那么网上怎么好多小伙伴说 UWP 的性能比 WPF 好?
因为 UWP 的渲染使用的是 DirectComposition 而 WPF 使用的 Desktop Window Manager,请不要在这里和我说 WPF 使用的 DX9 。
虽然 WPF 渲染是通过 Dx9 但是最后显示出来是需要 DWM ,所以上面这样说。
之外,UWP 使用 dot net core 编译出来的是 Native 本地代码,WPF 使用 dot net Framework 编译出来是 IL 代码,需要知道 编译出来 Native 代码的性能是 80% C++非托管。所以代码运行会快很多。
这时不要说 IL 可以针对每个 CPU 做优化,因为 dot net core 编译的代码就是对不同的 CPU 做优化。如果还需要对特殊CPU做优化,我还没找到。
系统支持
因为 WPF 发布的时候还没有 Win7 所以 WPF 是支持 xp 的。但是如果需要支持 xp 就需要使用不大于 .net Framework 4.0
的版本,如果比 4.0 大就无法支持 xp 啦。
需要知道,在 4.5之后 WPF 才修复很多 bug ,提升性能,能不支持 xp 就不要支持 xp。
UWP 发布的时候,因为使用的是 WinRT ,虽然底层和 WPF 一样使用的是 COM 但是添加了很多以前系统不支持的特性。微软为了减少开发或者基于某些考虑,于是UWP不支持以前系统,最低是 win10.
其他
虽然微软说 WPF 是支持触摸的,但是在 4.7 之前的触摸是很差的。所以 WPF 支持鼠标键盘。
但是 UWP 是支持触摸的,鼠标、键盘。
对于 触摸的支持,uwp 是做的很好的,不仅支持了 4.7.1 的指针消息而且还内部支持很多手势。
对于AR的输入,uwp也是支持的。
虽然 WPF 和 UWP 都使用 xaml 做界面,但是渲染是不相同的。 WPF 的渲染都是使用托管代码计算,然后通过通道使用 DirectX 9 渲染。渲染完成给 DWM 选择是否显示。但是 WPF 没有使用 DirectX 9 的性能,所以渲染是比较慢的。听说 WPF 可以使用 dx11 dx12都是使用优化级别是 fl9 。
但是 UWP 的渲染很快,因为他使用DirectComposition直接渲染,使用 DX11 渲染。DirectComposition 是通过集成 DWM 渲染的。组合的图形和动画通过 DirectComposition 构建然后传到 DWM 渲染到屏幕。所以使用 DirectComposition 不需要特殊的渲染框架。而且渲染的代码都是编译本地,比较多使用 DX11 ,但是对于很多硬件都支持 dx12 。
那么 DWM 的作用是什么,实际上从博客可以看到 DWM 实际作用 Windows 组合引擎或合成程序,需要每个窗口把显示的内容给屏外表面或缓冲区,缓冲区是系统给每个顶层窗口分配的,所有的 GDI、D3D、D2D 到先渲染到这里。然后 DWM 决定如何显示,是组合窗口还是做特效,最后再把缓存放到显卡。
参考 https://zhuanlan.zhihu.com/p/147499467
尽管WPF已经很完善,UMP看起来也很美好,但是WPF不能跨平台,UMP受限于API和不够完善,目前用的比较多的反而是WPF和xamarin。坏消息是,目前WPF项目开发都停滞不前,更新缓慢。
为解决客户端开发问题,目前,Windows10 1803版本之后,微软开始推WinUI,用来替代UWP和WPF。
So, 基于dot Net Core 的WPF 和 WinUI 3 都是很好的期待。
还有一个前途未知的Avalonia。
短期以WPF(.net core)和Avalonia项目!
C#运行在公共语言运行库(CLR)下,称为托管代码(managed code).
编译分为几个阶段:
Microsoft中间语言与Java字节码共享一种理念:他们都是低级语言,语法简单,可以很快转为本地机器码。优点是:平台无关,提高性能和语言互操作性。
ildasm是基于windows的实用程序,可以检查程序集的内容,包含清单和元数据。
共享程序集放在文件系统的一个特定的子目录树中,称为全局程序集缓存GAC。与私有程序集不同,不能简单地把共享程序集复制到对应的文件夹中,而需要专门安装到缓存中,可以用许多NET工具完成这个过程,其中包含对程序集的检查、在程序集缓存中设置一个小的文件夹层次结构,以确保程序集的完整性。
少从开发人员的角度来看,编写托管代码的最大好处是可以使用NET基类库。NET基类是一个内容丰富的托管代码类集合,它可以完成以前要通过Windows API来完成的绝大多数任务。NET基类的一个主要优点是它们非常直观和易用。可以通过WinCV浏览类库中的类,结构,接口和枚举。
System.Cosole
执行控制台I/Ousing System;
namespace ConsoleHello
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
C#有两个方法可确保变量在使用前进行了初始化:
类型推断(type inference)使用var关键字。声明变量的语法有些变化。编译器可以根据变量的初始化值"推断"变量的类型。
C#在变量之间有一个基本的区分,它把在类型级别声明的变量看作字段,而把在方法中声明的变量看作局部变量。如下:
using System;
namespace ConsoleHello
{
class Program
{
static int a = 10;
static void Main(string[] args)
{
int a = 22;
Console.WriteLine(a); // 22
Console.WriteLine(Program.a); // 10
}
}
}
常量总是静态的,但注意,不必(实际上,是不允许)在常量声明中包含修饰符static。
C#把数据类型分为两种:
值类型存储在堆栈中,而引用类型存储在托管堆上。
把基本类型如int和bool,规定为值类型,而把包含许多字段的较大类型(通常在有类的情况下〉规定为引用类型,C#设计这种方式的原因是可以得到最佳性能。如果要把自己的类型定义为值类型,就应把它声明为一个结构。
值类型:
bool System.Boolean 表示true/false
char System.Char 16位的Unicode字符
sbyte System.SByte 8位有符号整形
short System.Int16 16位有符号整形
int System.Int32 32位有符号整形
long System.Int64 64位有符号整形
byte System.Byte 8位无符号整形
ushort System.UInt16 16位无符号整形
uint System.UInt32 32位无符号整形
ulong System.Uint64 64位无符号整形
float System.Single 32位单精度浮点型
double System.Double 64位双精度浮点型
decimal System.Decimal 128位高精度十进制表示法
引用类型:
object System.Object 根类型,CTS其他类型都来自它(包含值类型)
string System.String Unicode字符串
针对值类型,通过ref关键字,可以在函数参数传递时,强制使用引用。
编译选项(/target):
/t:exe
控制台程序/t:library
有清单的类库/t:module
没有清单的组建/t:winexe
Windows应用程序编译后的类库,可被其他程序集引用,使用/r
选项,这样就可以很简单地引用其他程序集的内容。(通过DLL引用,无需像C++ library方式声明).
XML文档
C#支持XML格式文档,但是必须///
开发。
常见的xml文档注释标记有
等。
用于描述类型或类型成员函数,在其声明之前标注。
用于添加有关某个类型的补充信息,比如类图(怎样插入图像资源下面第四点再叙述)。标注可以嵌入在中,也可以跟在之后。嵌入在中会在命名空间页中对类的描述表中出现(图1);与并列则会在类的描述页出现。
可以嵌入于注释内,添加第二段说明:(此处嵌入于内)
标签用于方法声明的注释中,描述方法的一个参数。语法为description。
用于代码注释中的某个单词引用某个参数,使文档以某种独特方式(通常是斜体)来设置该单词的格式。语法为。
用于方法声明的注释,描述返回值。
标签用于从文本内指定链接。语法为。
标签指示文本放在“请参见”节中。语法为。cref=”member”对可以通过当前编译环境进行调用的成员或字段进行引用。编译器检查给定的代码元素是否存在,并将member传递给输出XML中的元素名。
预处理定义
#error "this is a error"
#warning "thisi ia a warning"
#regin Step 1 section
int a;
string b;
#endregin
#pragma waring disable/restore 169 // 抑制或者还原指定的编译警告
C#中的约定是命名变量时不使用任何前缀:string Result; string Message;
部分类
partial关键字允许把类、结构、接口放在多个文件中。一般放在class/struct/interface关键字前面。
扩展方法
有许多扩展类的方式。如果有类的源代码,继承(第4章所述)就是给对象添加功能的好方法。但如果没有源代码,该怎么办?此时可以使用扩展方法,它允许改变一个类,但不需要该类的源代码。
扩展方法是静态方法,它是类的一部分,但实际上没有放在类的源代码中。
此时必须做的所有工作就是创建一个静态类,把想要增加的方法添加为一个静态方法。
using System;
using System.Runtime.CompilerServices;
namespace ConsoleHello
{
class Program
{
static void Main(string[] args)
{
int a = 22;
Console.WriteLine($"Hello: {a}");
TestAgent t = new TestAgent();
t.Print();
t.addSomeValue(1000);
t.Print();
}
}
// 静态class和静态方法
static class TestAgentExtension
{
public static void addSomeValue(this TestAgent t, int val)
{
t.Abc += val;
}
}
class TestAgent
{
public int Abc { get; set; }
public TestAgent()
{
Abc = 100;
Console.WriteLine("Init abc parameter...");
}
public void Print()
{
Console.WriteLine(this.Abc);
}
}
}
C#中虚函数与抽象函数
Virtual方法(虚方法)
virtual 关键字用于在基类中修饰方法。virtual的使用会有两种情况:
情况1:在基类中定义了virtual方法,但在派生类中没有重写该虚方法。那么在对派生类实例的调用中,该虚方法使用的是基类定义的方法。
情况2:在基类中定义了virtual方法,然后在派生类中使用override重写该方法。那么在对派生类实例的调用中,该虚方法使用的是派生重写的方法。
Abstract方法(抽象方法)
abstract关键字只能用在抽象类中修饰方法,并且没有具体的实现。抽象方法的实现必须在派生类中使用override关键字来实现。
密封类与方法(sealed):
对于类表示不能继承,对于方法,表示不能重写该方法。
Net基类库大量使用了密封类,使希望从这些类中派生出自己的类的第三方开发人员无法访问这些类。
泛型:
using System;
using System.Collections;
using System.Collections.Generic;
namespace ConsoleHello
{
class Program
{
static void Main(string[] args)
{
// 强大,但是有box/unbox行为,性能损耗大
var list = new ArrayList();
list.Add(22);
list.Add("zhangsan");
list.Add(1.23);
foreach(var i2 in list)
{
Console.WriteLine($"{i2.GetType()}, {i2}");
}
int a = (int)list[0];
Console.WriteLine(a.GetType());
// 可以使用泛型集合替代
var l2 = new List();
l2.Add(11);
l2.Add(22);
}
}
}
泛型还可以添加约束,如:
public class MyClass
where T: IFoo, new()
{
// ...
}
其中where限定了类型T还必须实现了IFoo接口,new约束。
where T:stuct 对于结构约束,类型T必须是值类型
where T:class 类约束指定类型T必须是引用类型
where T:IFoo 指定类型T必须实现接口IFoo
where T:Foo 指定类型T必须派生自基类Foo
where T:new() 这是一个构造函数约束,指定类型T必须有一个默认构造函数
where T1:T2 这个约束也可以指定,类型T1派生自泛型类型T2。该约束也称为裸类型约束
委托
委托是C#实现回调函数的一种机制。
委托链:委托链是委托对象的集合。可以利用委托链调用集合中的委托所绑定的全部方法。继续在原有的基础上添加委托链的方法。
可以使用+=
运算符,为委托新增方法。
同样可以使用-=
运算符,为委托移除方法。
using System;
namespace ConsoleHello
{
class Program
{
public delegate int MyDeleg(int a);
static int fun1(int a)
{
Console.WriteLine($"fun1 {a}");
return a + 11;
}
static int fun2(int a)
{
Console.WriteLine($"fun2 {a}");
return a + 1100;
}
static void Main(string[] args)
{
MyDeleg t1 = fun2;
t1 += fun1;
// 参数相同,返回值单独返回,捕获每一个的返回值,需要使用如下方式
var calls = t1.GetInvocationList();
foreach(MyDeleg call in calls)
{
Console.WriteLine(call(3));
}
}
}
}
int[] a = new int[4];
var b = new int[]{1,2,3,4};
int[] c = {1,2,3,4};
int[,] d = new int[2,3]; // 多维数组
var e = d.Clone(); // 默认引用,Clone会完成浅拷贝。
// 还支持锯齿数组,通过各自的Length来判断
int[][] a1 = new int[3][];
a1[0] = new int[2];
a1[1] = new int[5]{1,2,3,4,5};
a1[2] = new int[3];
// yield 与 foreach
using System;
using System.Collections.Generic;
namespace ConsoleHello
{
class Program
{
static void Main(string[] args)
{
var list = new MyCollection();
foreach (var v in list)
{
Console.WriteLine(v);
}
}
public class MyCollection
{
public IEnumerator GetEnumerator()
{
yield return 123;
for(int i = 100; i < 120; i++)
{
yield return i;
}
}
}
}
}
is
进行检查两个对象是否兼容
as
进行显式的类型转换。失败时返回null.
sizeof
确定栈中类型需要的长度。
typeof
返回变量的类型,用于反射
int? a = null;
int? b = a + 10; // null
int c = b ?? -1; // -1
Console.WriteLine($"{b==null} {c}");
两个变量的比较:
Func f1 = s => String.Format("param val: {0}", s);
f1("abc");
Func f2 = (x,y) => x*y;
事件的订阅(回调函数):
using System;
using System.Threading;
namespace ConsoleHello
{
class Program
{
// 事件接收者(作用机理同 回调函数)
public static void subscribetor(int v)
{
Console.WriteLine($"event value: {v}");
}
static void Main(string[] args)
{
TestPublisher t = new TestPublisher();
t.NumerChageEvent += new TestPublisher.NumberChanged(subscribetor);
for(int i = 0; i < 10; i++)
{
Console.WriteLine("Add Something...");
t.AddSome(i);
Console.WriteLine("Sleep...\r\n");
Thread.Sleep(1000);
}
}
}
class TestPublisher
{
// 代理接口定义
public delegate void NumberChanged(int v);
// 事件对象,可能为null
public event NumberChanged NumerChangeEvent;
private int _Ticks = 0;
public void AddSome(int v)
{
Console.WriteLine($"Add Some {v}.");
this._Ticks += v;
NumerChangeEvent?.Invoke(this._Ticks);
}
}
}
System.String
提供基础的功能,但是频繁构建性能低下,需要使用StringBuilder
来替代,它性能更好,但是占用更多的内存。
using System;
using System.Text.RegularExpressions;
namespace ConsoleHello
{
class Program
{
static void Main(string[] args)
{
string oldText = "hello, andy@sz, ID: 10086, my email: [email protected], my phone: 13123456789.";
string re_number = @"\d+";
string re_email = @"\S+@\S+\.\S+";
Console.WriteLine("\r\nFind text for numbers:");
var mc = Regex.Matches(oldText, re_number);
foreach (Group g in mc)
{
Console.WriteLine("{0} {1}",g.Index,g.ToString());
}
Console.WriteLine("\r\nFind text for email:");
var mc2 = Regex.Matches(oldText, re_email);
foreach (Group g in mc2)
{
Console.WriteLine("{0} {1}", g.Index, g.ToString());
}
}
}
}
System.Collections 和 SYstem.Collections.Generic。
泛型集合:
Ref: Link
语言集查询(Language Integrated Query,LINQ)集成了 C# 编程语言中的查询语法,可以用相同的语法访问不同的数据源。LINQ提供了不同数据源的抽象层,所以可以使用相同的语法。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
namespace ConsoleHello
{
class Program
{
public static IList racers;
public static IList GetChampions()
{
if ( racers != null )
{
return racers;
}
racers = new List(40);
racers.Add(new Racer("zhang", "san", "Italy", 33, 15, new int[] { 1950, 1965 }, new string[] { "A" }));
racers.Add(new Racer("zhang", "si", "China", 20, 8, new int[] { 1951 }, new string[] { "A","B" }));
racers.Add(new Racer("zhang", "wu", "UK", 30, 21, new int[] { 1950 }, new string[] { "A","C" }));
racers.Add(new Racer("zhang", "liu", "USA", 15, 7, new int[] { 1950, 2000 }, new string[] { "C","D" }));
racers.Add(new Racer("li", "san", "UK", 9, 5, new int[] { 1950, 1951 }, new string[] { "A" }));
racers.Add(new Racer("wang", "san", "Italy", 51, 35, new int[] { 1951, 1965 }, new string[] { "A","D" }));
racers.Add(new Racer("wang", "san2", "China", 23, 14, new int[] { 1965, 2000 }, new string[] { "B","C" }));
racers.Add(new Racer("li", "san2", "Italy", 15, 3, new int[] { 1950 }, new string[] { "A","D","C" }));
racers.Add(new Racer("zhao", "qian", "China", 37, 25, new int[] { 1950 }, new string[] { "B","D" }));
return racers;
}
public static IList teams;
public static IList GetTeams()
{
if (racers != null)
{
return teams;
}
teams = new List()
{
new Team("Team1", 1965),
new Team("Team2", 2000,1951),
new Team("Team3", 1950, 1965, 1951 ),
new Team("Team4", 2001),
new Team("Team5", 1950, 2002),
new Team("Team6", 1950, 1965, 1951, 2001, 2002 ),
};
return teams;
}
static void Main(string[] args)
{
// LINQ 查询
var query = from r in GetChampions() where r.Country == "China" orderby r.Wins descending select r.Cars;
foreach(var v in query)
{
Console.WriteLine( string.Join("-",v));
}
var rs = GetChampions().Where((r, index) => r.LastName.StartsWith("s") && index % 2 != 0).Select(r=> (r.FirstName, r.LastName));
foreach (var v in rs)
{
Console.WriteLine("rs {0:A}", v);
}
var rs2 = from r in GetChampions()
from c in r.Cars
where c == "A" || c == "B"
orderby r.LastName
select r.FirstName+"-"+r.LastName;
foreach (var v in rs2)
{
Console.WriteLine("rs2 {0:A}", v);
}
}
[Serializable]
public class Racer : IComparable, IFormattable
{
public string FirstName;
public string LastName;
public int Wins;
public string Country;
public int Starts;
public string[] Cars;
public int[] Years;
public Racer(string firstName=null, string lastName=null, string country=null, int starts=0, int wins=0,
IEnumerable years=null, IEnumerable cars = null)
{
this.FirstName = firstName;
this.LastName = lastName;
this.Country = country;
this.Starts = starts;
this.Wins = wins;
this.Years = years.ToArray();
this.Cars = cars.ToArray();
}
public int CompareTo(Racer other)
{
return this.LastName.CompareTo(other?.LastName);
}
public override string ToString()
{
return string.Format("{0} {1}", FirstName, LastName);
}
public string ToString(string format)
{
return ToString(format, null);
}
public string ToString(string format, IFormatProvider formatProvider)
{
switch (format)
{
case null:
case "N":
return ToString();
case "F":
return FirstName;
case "L":
return LastName;
case "C":
return Country;
case "S":
return Starts.ToString();
case "W":
return Wins.ToString();
case "A":
return String.Format("{0} {1}, {2}; starts:{3}, wins:{4}", FirstName, LastName, Country, Starts, Wins);
default:
return ToString();
}
}
}
[Serializable]
public class Team
{
public string Name;
public int[] Years;
public Team(string name, params int[] years)
{
this.Name = name;
this.Years = years;
}
}
}
}
程序集由描述它的程序集元数据、描述导出类型和方法的类型元数据、MSIL代码和资源组成。
程序集的一个重要部分是程序集清单,它是元数据的一部分,描述了程序集和引用它所需要的所有信息,并列出了它所有的依赖关系。
附属程序集是只包含资源的程序集,它尤其适用于本地化。
程序集可以使用命令行实用工具 ildasm来 查看,这是一个 MsL反汇编程序。
在.NET之前的技术中,进程作为独立的边界来使用,每个进程都有其私有的虚拟内存;运行在一个进程中的应用程序不能写入另一个应用程序的内存,也不会因为这种方式破坏其他应用程序。
该进程用作应用程序之间的一个独立而安全的边界。在MT体 系结构中,应用程序有一个新的边界:应用程序域。
首先要知道2点:
补充一点:
相对来说,可以认为Invoke是同步的,而BeginInvoke是异步的
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Helloword
{
class Program
{
static int TakeALongWork(int data, int ms)
{
Console.WriteLine("Begin to work...");
Thread.Sleep(ms);
Console.WriteLine("Work completed!");
return data++;
}
public delegate int TakeALongWorkDelegate(int data, int ms);
static void cb_complete_func(IAsyncResult ar)
{
var dl = ar.AsyncState as TakeALongWorkDelegate;
Console.WriteLine("cb result: {0}", dl.EndInvoke(ar));
}
static void Main(string[] args)
{
Console.WriteLine("Hello,world");
// 直接调用
TakeALongWork(1, 1000);
Console.WriteLine("Method 1 over\r\n");
// 委托,然后同步查询
var dl = new TakeALongWorkDelegate(TakeALongWork);
IAsyncResult ar = dl.BeginInvoke(2, 2000, null, null);
while (!ar.IsCompleted)
{
Console.Write(".");
Thread.Sleep(50);
}
Console.WriteLine("Method2, Result: {0}\r\n", dl.EndInvoke(ar));
// 通过等待句柄查询
IAsyncResult ar2 = dl.BeginInvoke(3, 2000, null, null);
while (true)
{
Console.Write(".");
if ( ar2.AsyncWaitHandle.WaitOne(50,false) )
{
Console.WriteLine("Can get the result now.");
break;
}
}
Console.WriteLine("Method3, Result: {0}\r\n", dl.EndInvoke(ar2));
// 异步回调
dl.BeginInvoke(4, 2000, cb_complete_func, dl);
Console.WriteLine("Method4, Wait async result...\r\n");
Console.Read();
}
}
}
Thread
只要有一个前台线程在运行,应用程序的进程就在运行。如果多个前台线程在运行,而main方法结束了,应用程序的进程就仍然是激活的,直到所有前台线程完成其任务为止。
在默认情况下,用 Thread类 创建的线程是前台线程。线程池中的线程总是后台线程。
在用mread类创建线程时,可 以设置 IsBackgromd属性,以确定该线程是前台线程还是后台线程。
using System;
using System.Threading;
namespace Helloword
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello,world");
int a = 10;
var t1 = new Thread(() =>
{
Console.WriteLine("subthread running in a thread. {0}", Thread.CurrentThread.ManagedThreadId);
while (a > 0)
{
Console.Write(".");
Thread.Sleep(500);
a--;
}
Console.WriteLine("thread exit!");
});
t1.Start();
Console.WriteLine("main running in a thread. {0}", Thread.CurrentThread.ManagedThreadId);
while (a > 0)
{
Console.WriteLine("{0}", a);
Thread.Sleep(800);
}
Console.Read();
}
}
}
Task
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Helloword
{
class Program
{
static void TaskFunc1()
{
Console.WriteLine("Task func1 ID {0}, Thread: {1}", Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
}
static void TaskFunc2(Task t)
{
Console.WriteLine("Task {0} completed.", t.Id);
Console.WriteLine("Task func2 ID {0}, Thread: {1}", Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
}
static string TaskFunc3(object arg)
{
Console.WriteLine("Task func3 ID {0}, Thread: {1}", Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
string val = string.Format("you input is {0}", (int)arg);
return val;
}
static void Main(string[] args)
{
Console.WriteLine("Hello,world");
int nWorkers;
int nCompletionPortThs;
ThreadPool.GetMaxThreads(out nWorkers, out nCompletionPortThs );
Console.WriteLine("{0} {1}\r\n", nWorkers, nCompletionPortThs);
var t1 = Task.Factory.StartNew(TaskFunc1);
var t2 = new Task(TaskFunc1);
var t3 = t2.ContinueWith(TaskFunc2);
t3.ContinueWith(TaskFunc2);
t2.Start();
var t4 = new Task(TaskFunc3, 22);
t4.Start();
Console.WriteLine("\r\nt4 result: {0}\r\n", t4.Result);
Console.Read();
}
}
}
Parallel 在不同的线程中,使用不同的Task来执行一系列的事情:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Helloword
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello,world");
Parallel.For(1, 100, (i, pls) =>
{
Console.WriteLine("i:{0},\t task id:{1},\t thread Id:{2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(10);
if (i > 50)
{
pls.Break();
}
});
Console.Read();
}
}
}
可以用于多个线程的同步技术:
lock语句、interlocked类和Monitor类可用于进程内部的同步。
Mutex类、Semaphore类类 、Event类和 ReaderWriterLockSlim类提供了多个进程之间的线程同步。
http
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
namespace Helloword
{
class Program
{
static async Task http_test()
{
HttpClient c2 = new HttpClient();
try
{
var req = await c2.GetAsync("http://aicoder.vip/");
var resp = await req.Content.ReadAsStringAsync();
Console.WriteLine(resp);
}
catch (HttpRequestException e)
{
Console.WriteLine(e.Message);
}
}
static void http_req()
{
WebRequest req = WebRequest.Create("http://aicoder.vip");
req.Credentials = new NetworkCredential("admin", "xxxxx");
WebResponse resp = req.GetResponse();
Console.WriteLine(resp.Headers);
Console.WriteLine(resp.ContentLength);
}
static void Main(string[] args)
{
Console.WriteLine("Hello,world");
//WebClient c = new WebClient();
//var buff = c.DownloadData("http://aicoder.vip/");
//string s = Encoding.GetEncoding("UTF-8").GetString(buff);
//string charset = Regex.Match(s, "charset=(\\S+)").Value;
//Console.WriteLine(charset);
//Console.WriteLine(s);
//var ts = http_test();
//ts.Wait();
http_req();
Console.ReadLine();
}
}
}
Windows 服务是可以在系统启动时自动打开(不需要任何人登录计算机)的程序.
Whdows服务可以在没有交互式用户登录系统的情况下运行,在后台进行某些处理。
操作Windows服务需要3种程序:
服务的安装需要注册表配置。
服务程序实现服务的功能。服务程序需要3部分:
服务控制管理器(service contol Manager, SCM) 它可以把启动服务或停止服务的请求发送给服务.
Code OnStart,OnStop…
Add installer and config
installutil HelloService.exe
Basic Layout
<Window x:Class="WpfAppHello.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfAppHello"
mc:Ignorable="d"
Title="Basic Layout Test" Height="600" Width="800">
<Grid x:Name="grid1">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
Grid.RowDefinitions>
<TextBox Name="txt_question" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" FontFamily="JetBrains Mono"
FontSize="24" Foreground="{x:Static SystemColors.ActiveCaptionTextBrush}" Grid.Row="0">
<TextBox.Background>
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.00" Color="LightSeaGreen" />
<GradientStop Offset="0.70" Color="Indigo" />
<GradientStop Offset="1.00" Color="LightGreen" />
LinearGradientBrush.GradientStops>
LinearGradientBrush>
TextBox.Background>
Test Code
TextBox>
<Button Name="btn_go" Width="100" Height="30" Margin="10,10,0,10" HorizontalAlignment="Left" Grid.Row="1"
Click="btn_go_Click">
Ask why?
Button>
<TextBox Name="txt_answer" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Coral" Grid.Row="2">
Text Code
TextBox>
Grid>
Window>