大家好,我是Edison。
去年换工作时系统复习了一下.NET Core多线程相关专题,学习了一线码农老哥的《.NET 5多线程编程实战》课程,我将复习的知识进行了总结形成本专题。
深入分析使用Result方法死锁的原因.
场景1:带有同步上下文的编程模型中有可能会出现死锁
例如:WindowsForm、WPF
场景2:同步+异步的场景中也有可能出现死锁
Result => 同步等待,它其实违背了异步编程的理念(初心)
同步+异步混用会异常复杂,产生的Bug不易发现
比如:在WindowsForm下,同步调用异步方法(task.GetResult())时,async的callback进入了Queue,而主线程需要不断地读取Queue的内容来执行,就容易造成死锁。
为什么会出现死锁?
主线程 要结束阻塞,必须要等待 延续Task 执行完毕
延续Task 要执行完毕,必须要 主线程 从Queue中调取执行
var content = await client.GetStringAsync("http://cnblogs.com").ConfigureAwait(false);
private async void button1_Click(object sender, EventArgs e){var content = await GetContent();textBox1.Text = content;}
private void button1_Click(object sender, EventArgs e){var task = Task.Run(() =>{var content = GetContent().Result;return content;});textBox1.Text = task.Result;}
private void button1_Click(object sender, EventArgs e){SqlConnection connection = new SqlConnection("Server=LocalHost; Persist Security Info=False;Integrated Security=SSPI;Database= PostDB;");var length = connection.ExecuteScalarAsync<int>("select count(1) from Post").Result;textBox1.Text = length.ToString();}
await Task.Delay(1000 * 3);yield return urls;foreach (var url in await urlsTask){if (url.Contains("csdn") || url.Contains("cnblogs"))yield return url;}
while (await reader.ReadAsync()){yield return reader;}
foreach (var url in urls){tasks.Add(client.GetStringAsync(url));if (tasks.Count == 2){var strlist = await Task.WhenAll(tasks);Console.WriteLine($"{DateTime.Now}, length1={strlist[0].Length}, length2={strlist[1].Length} tid={Environment.CurrentManagedThreadId}");tasks.Clear();}}
if(t.IsFaulted){t.Exception.Handle(m => true);}
方式2:不处理,往外抛
if(t.IsFaulted){t.Exception.Handle(m => false);}
TaskScheduler.UnobservedTaskException += (sender, e) =>{Console.WriteLine(e.Exception.Message);Console.WriteLine($"tid={Environment.CurrentManagedThreadId}");};GC.Collect(); // 仅用来测试

