解决在同步方法中使用异步方法产生的线程死锁(死锁的主要原因是因为代码中线程对上下文的争夺)...

  1 /// <summary>
  2 /// 此类作用:解决在同步方法中使用异步方法产生的线程死锁
  3 /// 死锁的主要原因是因为代码中线程对上下文的争夺
  4 /// </summary>
  5 public static class AsyncExtend
  6 {
  7 /// <summary>
  8 /// 同步执行一个void类型的返回值操作
  9 /// </summary>
 10 /// <param name="task">Task method to execute</param>
 11 public static void RunSync(Func<Task> task)
 12 {
 13 var oldContext = SynchronizationContext.Current;
 14 var synch = new ExclusiveSynchronizationContext();
 15 SynchronizationContext.SetSynchronizationContext(synch);
 16 synch.Post(async _ =>
 17 {
 18 try
 19 {
 20 await task();
 21 }
 22 catch (Exception e)
 23 {
 24 synch.InnerException = e;
 25 throw;
 26 }
 27 finally
 28 {
 29 synch.EndMessageLoop();
 30 }
 31 }, null);
 32 synch.BeginMessageLoop();
 33 
 34 SynchronizationContext.SetSynchronizationContext(oldContext);
 35 }
 36 
 37 /// <summary>
 38 /// 同步执行一个Task《T》的异步任务
 39 /// </summary>
 40 /// <typeparam name="T">Return Type</typeparam>
 41 /// <param name="task">Task《T》 method to execute</param>
 42 /// <returns></returns>
 43 public static T RunSync<T>(Func<Task<T>> task)
 44 {
 45 var oldContext = SynchronizationContext.Current;
 46 var synch = new ExclusiveSynchronizationContext();
 47 SynchronizationContext.SetSynchronizationContext(synch);
 48 T ret = default(T);
 49 synch.Post(async _ =>
 50 {
 51 try
 52 {
 53 ret = await task();
 54 }
 55 catch (Exception e)
 56 {
 57 synch.InnerException = e;
 58 throw;
 59 }
 60 finally
 61 {
 62 synch.EndMessageLoop();
 63 }
 64 }, null);
 65 synch.BeginMessageLoop();
 66 SynchronizationContext.SetSynchronizationContext(oldContext);
 67 return ret;
 68 }
 69 
 70 /// <summary>
 71 /// 带异常的异步上下文
 72 /// </summary>
 73 private class ExclusiveSynchronizationContext : SynchronizationContext
 74 {
 75 private bool _done;
 76 public Exception InnerException { get; set; }
 77 readonly AutoResetEvent _workItemsWaiting = new AutoResetEvent(false);
 78 
 79 private readonly Queue<Tuple<SendOrPostCallback, object>> _items =
 80 new Queue<Tuple<SendOrPostCallback, object>>();
 81 
 82 public override void Send(SendOrPostCallback d, object state)
 83 {
 84 throw new NotSupportedException("We cannot send to our same thread");
 85 }
 86 
 87 public override void Post(SendOrPostCallback d, object state)
 88 {
 89 lock (_items)
 90 {
 91 _items.Enqueue(Tuple.Create(d, state));
 92 }
 93 _workItemsWaiting.Set();
 94 }
 95 
 96 public void EndMessageLoop()
 97 {
 98 Post(_ => _done = true, null);
 99 }
100 
101 public void BeginMessageLoop()
102 {
103 while (!_done)
104 {
105 Tuple<SendOrPostCallback, object> task = null;
106 lock (_items)
107 {
108 if (_items.Count > 0)
109 {
110 task = _items.Dequeue();
111 }
112 }
113 if (task != null)
114 {
115 task.Item1(task.Item2);
116 if (InnerException != null) // the method threw an exeption
117 {
118 throw new AggregateException("AsyncExtend.Run method threw an exception.", InnerException);
119 }
120 }
121 else
122 {
123 _workItemsWaiting.WaitOne();
124 }
125 }
126 }
127 
128 public override SynchronizationContext CreateCopy()
129 {
130 return this;
131 }
132 }
133 }

 

转载于:https://www.cnblogs.com/creater/p/6321997.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值