此入门教程是记录下方参考资料视频的过程
开发工具:Visual Studio 2019
async和await关键字可以让你写出和同步代码一样简洁且结构相同的异步代码
await
var result=await expression;
statement(s);
var awaiter=expression.GetAwaiter();
awaiter.OnCompleted(()=>
{
var result=awaiter.GetResult();
statement(s);
});
static async Task Main(string[] args)
{
}
async修饰符
异步方法如何执行
static async Task Main(string[] args)
{
}
可以await什么?
捕获本地状态
static async Task Main(string[] args)
{
}
static async void DisplayPrimeCounts()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine(await GetPrimesCountAsync(i * 1000000 + 2, 1000000));
}
}
static Task<int> GetPrimesCountAsync(int start, int count)
{
return Task.Run(() =>
ParallelEnumerable.Range(start, count).Count(n =>
Enumerable.Range(2, (int)Math.Sqrt(n) - 1).All(i => n % i > 0)));
}
await之后在哪个线程上执行
UI上的await
public MainWindow()
{
InitializeComponent();
}
async void Go()
{
this.Button1.IsEnabled = false;
for (int i = 1; i < 5; i++)
{
this.TextMessage.Text += await this.GetPrimesCountAsync(i * 1000000, 1000000) + " primes between " + (i * 1000000) + " and " + ((i + 1) * 1000000 - 1) + Environment.NewLine;
}
this.Button1.IsEnabled = true;
}
Task<int> GetPrimesCountAsync(int start, int count)
{
return Task.Run(() =>
ParallelEnumerable.Range(start, count).Count(n =>
Enumerable.Range(2, (int)Math.Sqrt(n) - 1).All(i => n % i > 0)));
}
private void Button1_Click(object sender, RoutedEventArgs e)
{
this.TextMessage.Text = null;
this.Go();
}
async void Go()
{
this.Button1.IsEnabled = false;
string[] urls = "www.bing.com www.baidu.com www.cnblogs.com".Split();
int totalLength = 0;
try
{
foreach (string url in urls)
{
var uri = new Uri("http://" + url);
byte[] data = await new WebClient().DownloadDataTaskAsync(uri);
this.TextMessage.Text += "Length of " + url + " is " + data.Length + Environment.NewLine;
totalLength += data.Length;
}
this.TextMessage.Text += "Total length " + totalLength;
}
catch (WebException e)
{
this.TextMessage.Text += "Error:" + e.Message;
}
finally
{
this.Button1.IsEnabled = true;
}
}
private void Button1_Click(object sender, RoutedEventArgs e)
{
this.TextMessage.Text = null;
this.Go();
}
伪代码:
为本线程设置同步上下文(WPF)
while(!程序结束)
{
等着消息队列中发生一些事情
发生了事情,是哪种消息?
键盘/鼠标消息->触发event handler
用户BeginInvoke/Invoke 消息->执行委托
}
附加到UI元素的event handler通过消息循环执行
因为在UI线程上await,continuation将消息发送到同步上下文上,该同步上下文通过消息循环执行,来保证整个Go方法伪并发的在UI线程上执行
与粗粒度的并发相比
1、例如使用BackgroundWorker,不推荐这样写异步函数
void Go()
{
for (int i = 1; i < 5; i++)
{
int result = this.GetPrimesCount(i * 1000000, 1000000);
this.Dispatcher.BeginInvoke(new Action(() =>
this.TextMessage.Text += result + " primes between " + (i * 1000000) + " and " + ((i + 1) * 1000000 - 1) + Environment.NewLine));
}
this.Dispatcher.BeginInvoke(new Action(() => this.Button1.IsEnabled = true));
}
int GetPrimesCount(int start, int count)
{
return ParallelEnumerable.Range(start, count).Count(n =>
Enumerable.Range(2, (int)Math.Sqrt(n) - 1).All(i => n % i > 0));
}
private async void Button1_Click(object sender, RoutedEventArgs e)
{
this.TextMessage.Text = null;
this.Button1.IsEnabled = false;
Task.Run(() => this.Go());
}
编写异步函数
static async Task Main(string[] args)
{
static async Task Main(string[] args)
{
}
static async Task Go()
{
await PrintAnswerToLife();
Console.WriteLine("Done");
}
static async Task PrintAnswerToLife()
{
await Task.Delay(5000);
int answer = 21 * 2;
Console.WriteLine(answer);
}
static Task PrintAnswerToLide()
{
var tcs = new TaskCompletionSource<object>();
var awaiter = Task.Delay(5000).GetAwaiter();
awaiter.OnCompleted(() =>
{
try
{
awaiter.GetResult();
int answer = 21 * 2;
Console.WriteLine(answer);
tcs.SetResult(null);
}
catch (Exception e)
{
tcs.SetException(e);
}
});
return tcs.Task;
}
编写异步函数,富客户端场景下
返回Task
static async Task Main(string[] args)
{
}
static async Task<int> GetAnswerToLiife()
{
await Task.Delay(5000);
int answer = 21 * 2;
return answer;
}
static async Task PrintAnswerToLife()
{
int answer = await GetAnswerToLife();
Console.WriteLine(answer);
}
static async Task<int> GetAnswerToLife()
{
await Task.Delay(5000);
int answer = 21 * 2;
return answer;
}
static void Main(string[] args)
{
}
static void Go()
{
PrintAnswerToLife();
Console.WriteLine("Done");
}
static void PrintAnswerToLife()
{
int answer = GetAnswerToLife();
Console.WriteLine(answer);
}
static int GetAnswerToLife()
{
Thread.Sleep(5000);
int answer = 21 * 2;
return answer;
}
C#中如何设计异步函数
编译器能对异步函数生成Task意味着什么?
异步调用图执行
static async Task Main(string[] args)
{
并行(Parallelism)
var task1=PrintAnswerToLife();
var task2=PrintAnswerToLife();
await task1;
await task2;
异步Lambda表达式
static async Task Main(string[] args)
{
Func unnamed = async () =>
{
await Task.Delay(1000);
Console.WriteLine("Foo");
};
await NamedMethod();
await unnamed();
}
static async Task NamedMethod()
{
await Task.Delay(1000);
Console.WriteLine("Foo");
}
myButton.Click+=async (sender,args)=>
{
await Task.Delay(1000);
myButton.Content="Done";
}
相当于
myButton.Click+=ButtonHandler;
async void ButtonHandler(object sender,EventArgs args)
{
await Task.Delay(1000);
myButton.Content="Done";
}
static async Task Main(string[] args)
{
Funcint>> unnamed = async () =>
{
await Task.Delay(1000);
return 123;
};
int answer = await unnamed();
}
异步函数 结束
Original: https://www.cnblogs.com/Leo_wl/p/16521250.html
Author: HackerVirus
Title: 异步函数
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/547297/
转载文章受原作者版权保护。转载请注明原作者出处!