C# Microsoft.Bcl.Async中是否有类似ExceptionDispatchInfo的代码?

C# Microsoft.Bcl.Async中是否有类似ExceptionDispatchInfo的代码?,c#,.net,task-parallel-library,async-await,C#,.net,Task Parallel Library,Async Await,有没有类似于in?我找不到类似的东西 这个问题是由我的想法引发的。当异常的父任务可用时,我可以使用@StephenCleary建议的task.GetAwaiter().GetResult() 当它不可用时,我的选项是什么?以下是例外DispatchInfo的实现。据我测试,它似乎与Microsoft.NET 4.0兼容 public sealed class ExceptionDispatchInfo { readonly Exception _exception; readon

有没有类似于in?我找不到类似的东西

这个问题是由我的想法引发的。当异常的父任务
可用时,我可以使用@StephenCleary建议的
task.GetAwaiter().GetResult()


当它不可用时,我的选项是什么?

以下是
例外DispatchInfo
的实现。据我测试,它似乎与Microsoft.NET 4.0兼容

public sealed class ExceptionDispatchInfo
{
    readonly Exception _exception;
    readonly object _source;
    readonly string _stackTrace;

    const BindingFlags PrivateInstance = BindingFlags.Instance | BindingFlags.NonPublic;
    static readonly FieldInfo RemoteStackTrace = typeof(Exception).GetField("_remoteStackTraceString", PrivateInstance);
    static readonly FieldInfo Source = typeof(Exception).GetField("_source", PrivateInstance);
    static readonly MethodInfo InternalPreserveStackTrace = typeof(Exception).GetMethod("InternalPreserveStackTrace", PrivateInstance);

    private ExceptionDispatchInfo(Exception source)
    {
        _exception = source;
        _stackTrace = _exception.StackTrace + Environment.NewLine;
        _source = Source.GetValue(_exception);
    }

    public Exception SourceException { get { return _exception; } }

    public static ExceptionDispatchInfo Capture(Exception source)
    {
        if (source == null)
            throw new ArgumentNullException("source");

        return new ExceptionDispatchInfo(source);
    }

    public void Throw()
    {
        try
        {
            throw _exception;
        }
        catch
        {
            InternalPreserveStackTrace.Invoke(_exception, new object[0]);
            RemoteStackTrace.SetValue(_exception, _stackTrace);
            Source.SetValue(_exception, _source);
            throw;
        }
    }
}

我已经尝试过了,但它并没有通过所有的测试。我的意思是,它提供了基本行为,但在更复杂的情况下(如多次投掷、重新捕获等)会失败

作为本课程的一部分,我为这个类制作了一个后端端口,它可以在现代Mono、旧Mono(2.6*之前)和任何Microsoft.NET 2.0到4.0版本中使用

*:米格尔·德伊卡扎给了我一点提示:)

下面的代码当前仅在功能分支上,它最终将移动到主分支(以及.NET 2.0:的任务),此时它将通过。我把它留在这里,以防有人需要它

如果您发现任何问题,欢迎在项目的github(上面链接)的问题跟踪器上发布错误报告

#if NET20 || NET30 || NET35 || NET40

using System.Reflection;

namespace System.Runtime.ExceptionServices
{
    /// <summary>
    /// The ExceptionDispatchInfo object stores the stack trace information and Watson information that the exception contains at the point where it is captured. The exception can be thrown at another time and possibly on another thread by calling the ExceptionDispatchInfo.Throw method. The exception is thrown as if it had flowed from the point where it was captured to the point where the Throw method is called.
    /// </summary>
    public sealed class ExceptionDispatchInfo
    {
        private static FieldInfo _remoteStackTraceString;

        private Exception _exception;
        private object _stackTraceOriginal;
        private object _stackTrace;

        private ExceptionDispatchInfo(Exception exception)
        {
            _exception = exception;
            _stackTraceOriginal = _exception.StackTrace;
            _stackTrace = _exception.StackTrace;
            if (_stackTrace != null)
            {
                _stackTrace += Environment.NewLine + "---End of stack trace from previous location where exception was thrown ---" + Environment.NewLine;
            }
            else
            {
                _stackTrace = string.Empty;
            }
        }

        /// <summary>
        /// Creates an ExceptionDispatchInfo object that represents the specified exception at the current point in code.
        /// </summary>
        /// <param name="source">The exception whose state is captured, and which is represented by the returned object.</param>
        /// <returns>An object that represents the specified exception at the current point in code. </returns>
        public static ExceptionDispatchInfo Capture(Exception source)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            return new ExceptionDispatchInfo(source);
        }

        /// <summary>
        /// Gets the exception that is represented by the current instance.
        /// </summary>
        public Exception SourceException
        {
            get
            {
                return _exception;
            }
        }

        private static FieldInfo GetFieldInfo()
        {
            if (_remoteStackTraceString == null)
            {
                // ---
                // Code by Miguel de Icaza

                FieldInfo remoteStackTraceString =
                    typeof(Exception).GetField("_remoteStackTraceString",
                    BindingFlags.Instance | BindingFlags.NonPublic); // MS.Net

                if (remoteStackTraceString == null)
                    remoteStackTraceString = typeof(Exception).GetField("remote_stack_trace",
                        BindingFlags.Instance | BindingFlags.NonPublic); // Mono pre-2.6

                // ---
                _remoteStackTraceString = remoteStackTraceString;
            }
            return _remoteStackTraceString;
        }

        private static void SetStackTrace(Exception exception, object value)
        {
            FieldInfo remoteStackTraceString = GetFieldInfo();
            remoteStackTraceString.SetValue(exception, value);
        }

        /// <summary>
        /// Throws the exception that is represented by the current ExceptionDispatchInfo object, after restoring the state that was saved when the exception was captured.
        /// </summary>
        public void Throw()
        {
            try
            {
                throw _exception;
            }
            catch (Exception exception)
            {
                GC.KeepAlive(exception);
                var newStackTrace = _stackTrace + BuildStackTrace(Environment.StackTrace);
                SetStackTrace(_exception, newStackTrace);
                throw;
            }
        }

        private string BuildStackTrace(string trace)
        {
            var items = trace.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
            var newStackTrace = new Text.StringBuilder();
            var found = false;
            foreach (var item in items)
            {
                // Only include lines that has files in the source code
                if (item.Contains(":"))
                {
                    if (item.Contains("System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()"))
                    {
                        // Stacktrace from here on will be added by the CLR
                        break;
                    }
                    if (found)
                    {
                        newStackTrace.Append(Environment.NewLine);
                    }
                    found = true;
                    newStackTrace.Append(item);
                }
                else if (found)
                {
                    break;
                }
            }
            var result = newStackTrace.ToString();
            return result;
        }
    }
}

#endif
#如果NET20 | NET30 | NET35 | NET40
运用系统反思;
命名空间System.Runtime.ExceptionServices
{
/// 
///ExceptionDispatchInfo对象存储异常在捕获点包含的堆栈跟踪信息和Watson信息。通过调用ExceptionDispatchInfo.Throw方法,可以在另一个时间抛出异常,也可能在另一个线程上抛出异常。异常就像从捕获点流出一样被抛出它被捕获到调用Throw方法的位置。
/// 
公共密封类例外DispatchInfo
{
私有静态FieldInfo _remoteStackTraceString;
私人例外(private Exception);
私有对象_stackTraceOriginal;
私有对象_stackTrace;
私有例外DispatchInfo(例外)
{
_例外=例外;
_stackTraceOriginal=\u exception.StackTrace;
_stackTrace=\u exception.stackTrace;
如果(_stackTrace!=null)
{
_stackTrace+=Environment.NewLine+“--引发异常的上一个位置的堆栈跟踪结束----“+Environment.NewLine;
}
其他的
{
_stackTrace=string.Empty;
}
}
/// 
///创建ExceptionDispatchInfo对象,该对象表示代码中当前点的指定异常。
/// 
///其状态被捕获并由返回对象表示的异常。
///表示代码中当前点的指定异常的对象。
公共静态异常DispatchInfo捕获(异常源)
{
if(source==null)
{
抛出新的ArgumentNullException(“源”);
}
返回新的ExceptionDispatchInfo(来源);
}
/// 
///获取由当前实例表示的异常。
/// 
公共异常源异常
{
得到
{
返回异常;
}
}
私有静态FieldInfo GetFieldInfo()
{
if(_remoteStackTraceString==null)
{
// ---
//Miguel de Icaza编写的代码
FieldInfo remoteStackTraceString=
typeof(Exception).GetField(“\u remoteStackTraceString”,
BindingFlags.Instance | BindingFlags.NonPublic);//MS.Net
如果(remoteStackTraceString==null)
remoteStackTraceString=typeof(Exception).GetField(“远程堆栈跟踪”,
BindingFlags.Instance | BindingFlags.NonPublic);//Mono-pre-2.6
// ---
_remoteStackTraceString=remoteStackTraceString;
}
返回_remoteStackTraceString;
}
私有静态void SetStackTrace(异常、对象值)
{
FieldInfo remoteStackTraceString=GetFieldInfo();
remoteStackTraceString.SetValue(异常,值);
}
/// 
///还原捕获异常时保存的状态后,引发由当前ExceptionDispatchInfo对象表示的异常。
/// 
公开作废
{
尝试
{
抛出异常;
}
捕获(异常)
{
GC.KeepAlive(例外);
var newStackTrace=\u stackTrace+BuildStackTrace(Environment.stackTrace);
SetStackTrace(_异常,newStackTrace);
投掷;
}
}
私有字符串BuildStackTrace(字符串跟踪)
{
var items=trace.Split(new[]{Environment.NewLine},StringSplitOptions.RemoveEmptyEntries);
var newStackTrace=new Text.StringBuilder();
var=false;
foreach(项目中的var项目)
{
//仅包括源代码中包含文件的行
如果(项包含(“:”)
{
if(item.Contains(“System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()”)
{
//从此处开始的Stacktrace将由CLR添加
打破
}
如果(找到)
{
newStackTrace.Append(Environment.NewLine);
}
发现=真;
newStackTrace.Append(