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


      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 }
  • 相关阅读:
    shipyard 管理swarm集群(附etcd发现服务方法)
    docker swarm 简易版
    SQL 优化:连接表查询优化
    【Java框架型项目从入门到装逼】第十四节 查询用户列表展现到页面
    【Java框架型项目从入门到装逼】第十三节 用户新增功能完结篇
    【Java框架型项目从入门到装逼】第十二节 项目分层
    【Java框架型项目从入门到装逼】第十一节 用户新增之把数据传递到后台
    【Java框架型项目从入门到装逼】第九节
    【Java框架型项目从入门到装逼】第八节
    【Java框架型项目从入门到装逼】第七节
  • 原文地址:https://www.cnblogs.com/creater/p/6321997.html
Copyright © 2020-2023  润新知