双SynchronizationContext同步请求造成UI死锁

代码

private void btnRun_Click(object sender, EventArgs e)

{

    var sc = SynchronizationContext.Current;

    //①

    sc.Send(o =>

    {

	btnRun.Text = DateTime.Now.ToString();

	var t = new Thread(() =>

	{

	    //②

	    sc.Send(oo =>

	    {

		Thread.Sleep(1000);

		btnRun.Text = DateTime.Now.ToString();

	    }, null);

	});

	t.Start();

	t.Join();

    }, null);

}

解释

①处开始占用SynchronizationContext,并开始同步执行一直等待②处执行完毕。但②处也申请占用SynchronizationContext以将自己的代码执行完毕。砰~DeadLock条件成立!

解决

将同步调用改成异步,破坏死锁条件。将②处的“sc.Send”改成“sc.Post”即可。

结论

牵涉到“同步”与“资源占用”的话,要注意是否可能会造成死锁。

个人挺不愿花许多心思在业务代码上,乱刀斩乱麻,直接避免“同步”与“资源占用”,即避免使用SynchronizationContext.Send(),统一使用SynchronizationContext.Post()。

参考

UI thread client callback和UI thread WCF Service一起工作时死锁的形成原因及解决方法


你可能感兴趣的:(context)