马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
再次碰到dotnet的第三方组件标题,就是hangfire的CoreBackgroundJobPerformer会导致死锁,它是作为hagnfire服务端的job实验器的,它非常的关键,是job可以或许运行的关键,这些库大概读是从很早的dotnetfremework期间移植过来的(我推测的),同样的存在同步调用异步代码的标题,会导致死锁。
它有标题的代码如下:- namespace Hangfire.Server
- {
- internal sealed class CoreBackgroundJobPerformer : IBackgroundJobPerformer
- {
- private object InvokeMethod(PerformContext context, object instance, object[] arguments)
- if (context.BackgroundJob.Job == null) return null;
- try
- {
- var methodInfo = context.BackgroundJob.Job.Method;
- var method = new BackgroundJobMethod(methodInfo, instance, arguments);
- var returnType = methodInfo.ReturnType;
- if (returnType.IsTaskLike(out var getTaskFunc))
- {
- if (_taskScheduler != null)
- {
- return InvokeOnTaskScheduler(context, method, getTaskFunc);
- }
- return InvokeOnTaskPump(context, method, getTaskFunc);
- }
- return InvokeSynchronously(method);
- }
- catch (ArgumentException ex)
- {
- HandleJobPerformanceException(ex, context.CancellationToken, context.BackgroundJob);
- throw;
- }
- catch (AggregateException ex)
- {
- HandleJobPerformanceException(ex.InnerException, context.CancellationToken, context.BackgroundJob);
- throw;
- }
- catch (TargetInvocationException ex)
- {
- HandleJobPerformanceException(ex.InnerException, context.CancellationToken, context.BackgroundJob);
- throw;
- }
- catch (Exception ex) when (ex.IsCatchableExceptionType())
- {
- HandleJobPerformanceException(ex, context.CancellationToken, context.BackgroundJob);
- throw;
- }
- }
- private object InvokeOnTaskScheduler(PerformContext context, BackgroundJobMethod method, Func<object, Task> getTaskFunc)
- {
- var scheduledTask = Task.Factory.StartNew(
- InvokeOnTaskSchedulerInternal,
- method,
- CancellationToken.None,
- TaskCreationOptions.None,
- _taskScheduler);
- var result = scheduledTask.GetAwaiter().GetResult();//同步执行异步
- if (result == null) return null;
- return getTaskFunc(result).GetTaskLikeResult(result, method.ReturnType);
- }
- private static object InvokeOnTaskSchedulerInternal(object state)
- {
- // ExecutionContext is captured automatically when calling the Task.Factory.StartNew
- // method, so we don't need to capture it manually. Please see the comment for
- // synchronous method execution below for details.
- return ((BackgroundJobMethod)state).Invoke();
- }
- private static object InvokeOnTaskPump(PerformContext context, BackgroundJobMethod method, Func<object, Task> getTaskFunc)
- {
- // Using SynchronizationContext here is the best default option, where workers
- // are still running on synchronous dispatchers, and where a single job performer
- // may be used by multiple workers. We can't create a separate TaskScheduler
- // instance of every background job invocation, because TaskScheduler.Id may
- // overflow relatively fast, and can't use single scheduler for multiple performers
- // for better isolation in the default case – non-default external scheduler should
- // be used. It's also great to preserve backward compatibility for those who are
- // using Parallel.For(Each), since we aren't changing the TaskScheduler.Current.
- var oldSyncContext = SynchronizationContext.Current;
- try
- {
- using (var syncContext = new InlineSynchronizationContext())
- using (var cancellationEvent = context.CancellationToken.ShutdownToken.GetCancellationEvent())
- {
- SynchronizationContext.SetSynchronizationContext(syncContext);
- var result = InvokeSynchronously(method);
- if (result == null) return null;
- var task = getTaskFunc(result);
- var asyncResult = (IAsyncResult)task;
- var waitHandles = new[] { syncContext.WaitHandle, asyncResult.AsyncWaitHandle, cancellationEvent.WaitHandle };
- while (!asyncResult.IsCompleted && WaitHandle.WaitAny(waitHandles) == 0)//这里也同样
- {
- var workItem = syncContext.Dequeue();
- workItem.Item1(workItem.Item2);
- }
- return task.GetTaskLikeResult(result, method.ReturnType);
- }
- }
- finally
- {
- SynchronizationContext.SetSynchronizationContext(oldSyncContext);
- }
- }
复制代码 有标题的代码就是
var result = scheduledTask.GetAwaiter().GetResult();
以及
while (!asyncResult.IsCompleted && WaitHandle.WaitAny(waitHandles) == 0)
制止现在1.8.22版本照旧没有办理这个标题,有人提了issue了,但是要到2.0.0版本才会办理。
免责声明:如果侵犯了您的权益,请联系站长及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金. |