考虑下列代码:
CancellationTokenSource cts0 = new CancellationTokenSource(),cts1 = new CancellationTokenSource();
try
{
    var task = Task.Run(() => { throw new OperationCanceledException("123",cts0.Token); },cts1.Token);
    task.Wait();
}
catch (AggregateException ae) { Console.WriteLine(ae.InnerException); }

由于MSDN任务应处于故障状态,因为它的令牌不匹配异常的令牌(并且IsCancellationRequested为false):

If the token’s IsCancellationRequested property returns false or if the exception’s token does not match the Task’s token,the OperationCanceledException is treated like a normal exception,causing the Task to transition to the Faulted state.

当我在控制台应用程序中使用.NET 4.5.2启动此代码时,我将在取消状态中获取任务(聚合异常包含未知的TaskCanceledExeption,而不是原始的).原始异常的所有信息都会丢失(消息,内部异常,自定义数据).

我也注意到Task.Wait的行为与OperationCanceledException的情况下的等待任务不同.

try { Task.Run(() => { throw new InvalidOperationException("123"); }).Wait(); } // 1
catch (AggregateException ae) { Console.WriteLine(ae.InnerException); }

try { await Task.Run(() => { throw new InvalidOperationException("123"); }); } // 2
catch (InvalidOperationException ex) { Console.WriteLine(ex); }

try { Task.Run(() => { throw new OperationCanceledException("123"); }).Wait(); } // 3 
catch (AggregateException ae) { Console.WriteLine(ae.InnerException); }

try { await Task.Run(() => { throw new OperationCanceledException("123"); }); } // 4
catch (OperationCanceledException ex) { Console.WriteLine(ex); }

情况1和2产生几乎相同的结果(仅在StackTrace中有所不同),但是当我将异常更改为OperationCanceledException时,我得到非常不同的结果:在没有原始数据的情况下为3的未知TaskCanceledException,以及在具有所有原始数据的情况下期望的OpeartionCanceledException (消息等).

所以问题是:MSDN是否包含不正确的信息?还是.NET中的错误?或者也许只是我不明白的东西?

解决方法

这是一个bug. Task.Run在引导下调用任务< Task> .Factory.StartNew.该内部任务正在获得正确的“故障状态”.包装任务不是.

你可以通过调用来解决这个bug

Task.Factory.StartNew(() => { throw new OperationCanceledException("123",cts1.Token,TaskCreationoptions.DenyChildAttach,TaskScheduler.Default);

虽然,您将丢失任务解除的另一个功能.看到:
Task.Run vs Task.Factory.StartNew

更多细节:

这里是Task.Run的代码,您可以看到它正在创建一个包装UnwrapPromise(它来自Task< TResult&gt ;:::

public static Task Run(Func<Task> function,CancellationToken cancellationToken)
{
    // Check arguments
    if (function == null) throw new ArgumentNullException("function");
    Contract.EndContractBlock();

    cancellationToken.ThrowIfSourcedisposed();

    // Short-circuit if we are given a pre-canceled token
    if (cancellationToken.IsCancellationRequested)
        return Task.FromCancellation(cancellationToken);

    // Kick off initial Task,which will call the user-supplied function and yield a Task.
    Task<Task> task1 = Task<Task>.Factory.StartNew(function,cancellationToken,TaskScheduler.Default);

    // Create a promise-style Task to be used as a proxy for the operation
    // Set lookForOce == true so that unwrap logic can be on the lookout for OCEs thrown as faults from task1,to support in-delegate cancellation.
    UnwrapPromise<VoidTaskResult> promise = new UnwrapPromise<VoidTaskResult>(task1,lookForOce: true);

    return promise;
}

它调用的Task构造函数不会取消取消令牌(因此它不知道内部任务的取消令牌).请注意,它会创建一个默认的CancellationToken.这是它所调用的ctor:

internal Task(object state,TaskCreationoptions creationoptions,bool promiseStyle)
{
    Contract.Assert(promiseStyle,"Promise CTOR: promiseStyle was false");

    // Check the creationoptions. We only allow the AttachedToParent option to be specified for promise tasks.
    if ((creationoptions & ~TaskCreationoptions.AttachedToParent) != 0)
    {
        throw new ArgumentOutOfRangeException("creationoptions");
    }

    // m_parent is readonly,and so must be set in the constructor.
    // Only set a parent if AttachedToParent is specified.
    if ((creationoptions & TaskCreationoptions.AttachedToParent) != 0)
        m_parent = Task.InternalCurrent;

    TaskConstructorCore(null,state,default(CancellationToken),creationoptions,InternalTaskOptions.PromiseTask,null);
}

外部任务(UnwrapPromise添加了一个延续).继续检查内部任务.在内部任务发生故障的情况下,它考虑发现一个OperationCanceledException作为指示取消(不管匹配的令牌).以下是UnwrapPromise< TResult> .TrySetFromTask(下面也是调用堆栈,显示它被调用的位置).注意故障状态:

private bool TrySetFromTask(Task task,bool lookForOce)
{
    Contract.Requires(task != null && task.IsCompleted,"TrySetFromTask: Expected task to have completed.");

    bool result = false;
    switch (task.Status)
    {
        case TaskStatus.Canceled:
            result = TrySetCanceled(task.CancellationToken,task.GetCancellationExceptiondispatchInfo());
            break;

        case TaskStatus.Faulted:
            var edis = task.GetExceptiondispatchInfos();
            ExceptiondispatchInfo oceEdi;
            OperationCanceledException oce;
            if (lookForOce && edis.Count > 0 &&
                (oceEdi = edis[0]) != null &&
                (oce = oceEdi.sourceException as OperationCanceledException) != null)
            {
                result = TrySetCanceled(oce.CancellationToken,oceEdi);
            }
            else
            {
                result = TrySetException(edis);
            }
            break;

        case TaskStatus.RanToCompletion:
            var taskTResult = task as Task<TResult>;
            result = TrySetResult(taskTResult != null ? taskTResult.Result : default(TResult));
            break;
    }
    return result;
}

调用堆栈

mscorlib.dll!System.Threading.Tasks.Task<System.Threading.Tasks.VoidTaskResult>.TrySetCanceled(System.Threading.CancellationToken tokenToRecord,object cancellationException) Line 645 C#
    mscorlib.dll!System.Threading.Tasks.UnwrapPromise<System.Threading.Tasks.VoidTaskResult>.TrySetFromTask(System.Threading.Tasks.Task task,bool lookForOce) Line 6988 + 0x9f bytes   C#
    mscorlib.dll!System.Threading.Tasks.UnwrapPromise<System.Threading.Tasks.VoidTaskResult>.ProcessCompletedOuterTask(System.Threading.Tasks.Task task) Line 6956 + 0xe bytes  C#
    mscorlib.dll!System.Threading.Tasks.UnwrapPromise<System.Threading.Tasks.VoidTaskResult>.InvokeCore(System.Threading.Tasks.Task completingTask) Line 6910 + 0x7 bytes   C#
    mscorlib.dll!System.Threading.Tasks.UnwrapPromise<System.Threading.Tasks.VoidTaskResult>.Invoke(System.Threading.Tasks.Task completingTask) Line 6891 + 0x9 bytes   C#
    mscorlib.dll!System.Threading.Tasks.Task.FinishContinuations() Line 3571    C#
    mscorlib.dll!System.Threading.Tasks.Task.FinishStageThree() Line 2323 + 0x7 bytes   C#
    mscorlib.dll!System.Threading.Tasks.Task.FinishStageTwo() Line 2294 + 0x7 bytes C#
    mscorlib.dll!System.Threading.Tasks.Task.Finish(bool bUserDelegateExecuted) Line 2233   C#
    mscorlib.dll!System.Threading.Tasks.Task.ExecuteWithThreadLocal(ref System.Threading.Tasks.Task currentTaskSlot) Line 2785 + 0xc bytes  C#
    mscorlib.dll!System.Threading.Tasks.Task.ExecuteEntry(bool bPreventDoubleExecution) Line 2728   C#
    mscorlib.dll!System.Threading.Tasks.Task.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() Line 2664 + 0x7 bytes   C#
    mscorlib.dll!System.Threading.ThreadPoolWorkQueue.dispatch() Line 829   C#
    mscorlib.dll!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() Line 1170 + 0x5 bytes   C#

它注意到OperationCanceledException,并调用TrySetCanceled将任务置于已取消状态.

放在一边

另外需要注意的是,当您开始使用异步方法时,没有一种方法可以使用异步方法注册取消令牌.因此,在异步方法中遇到的任何OperationCancelledException被认为是取消.
看到
Associate a CancellationToken with an async method’s Task

c# – Task.Wait在OperationCanceledException的情况下出现意外行为的更多相关文章

  1. ios – iPhone崩溃日志不能正确地符号化并且是双重间隔的

    任何建议超过欢迎.谢谢.解决方法当这件事发生在我身上时,它只是我通过电子邮件收到的日志.如果我记得,至少有一些是在.msg文件中,我不得不把它们拿出来.它可能是Exchange编码更改.如果你显示不可见的字符,你可能会看到每个字符之间的东西.您可以找到并替换它们以删除它们或更改编辑器中的编码.

  2. xamarin.ios – 没有找到ViewController ::.ctor(System.IntPtr)的构造函数

    我有一个问题,我的Monotouch应用程序有时在收到内存警告后才会崩溃.请参见下面的堆栈跟踪.堆栈跟踪是正确的,因为指定的类缺少构造函数获取IntPtr参数.但是这是有意的,因为我在应用程序中根本不使用InterfaceBuilder.那为什么会这样呢?

  3. ios – 在/usr/lib/system/libcache.dylib中,缺少必需的架构armv6

    在试图为iphoneos编写一个虚拟程序时,Xcode4,gcc似乎没有超出初始的sysroot目录如果我把sysroot,以下作品,但感觉非常干酪,而且不可伸缩.这里发生了什么?

  4. ios – Iphone / Ipad在缩放时崩溃

    i=hUb1GHJ6有没有人有什么可能出错的线索?解决方法我们正在做很多调试,我们终于找到了一个解决方案.我们有一个“跳过导航”链接,只有在您的键盘上按“标签”时才显示.这最初设置为“text-indent:-10000px”.这可能导致视口宽度超过10000像素,然后导致手机使用太多内存,然后最终崩溃.我们已经通过删除这个CSS规则来解决这个问题,所以blush.no不会崩溃那么多了.Iphone仍然有内存泄漏的问题,直到他们解决这个问题,网站有时会崩溃,但不会像以前那样接近.

  5. xamarin.ios – 如何使用System.Drawing.Color?

    我昨天遇到了问题.我想在Android和iOS项目中使用System.Drawing.Color结构.Xamarin文档声称MonoTouch框架具有System.Drawing.Color结构(link-http://iosapi.xamarin.com/?link=T:System.Drawing.Color).但是在monotouch.dll命名空间中,System.Drawing没有名称为

  6. ios – 异常类型:EXC_CRASH(SIGABRT)

    有没有人知道这次崩溃?解决方法这不是崩溃,因异常而中止.这意味着您的应用程序正在将错误数据传递给系统例程,并且例程说它很糟糕且无法继续,因此它会杀死您的应用程序.控制台应该显示出错的地方.可能发生的一个常见异常是尝试从一个只有n个对象的数组中获取第一个对象.控制台将显示一条消息.因此,请检查控制台以查看可能发生的情况.

  7. Project Perfect让Swift在服务器端跑起来-Perfect in Visual Studio Code (四)

    VisualStudioCode是一个轻量级的编辑器,但也功能丰富,通过插件你可以完成如Cordova,ReactNative,NodeJS,PHP,ASP.NETCore的开发。上文通过VisualStudioCode对Perfect文件进行编辑,但编译过程还是在终端中完成。其实通过对VisualStudioCode添加tasks.json就可以完成对Perfect项目的编译工作。这里有个疑问,为何选择VisualStudioCode?这是一个好复杂的三角关系,如图:Microsoft+Swift+Li

  8. Project Perfect让Swift在服务器端跑起来-Perfect in Visual St

    VisualStudioCode是一个轻量级的编辑器,但也功能丰富,通过插件你可以完成如Cordova,ReactNative,NodeJS,PHP,ASP.NETCore的开发。上文通过VisualStudioCode对Perfect文件进行编辑,但编译过程还是在终端中完成。其实通过对VisualStudioCode添加tasks.json就可以完成对Perfect项目的编译工作。这里有个疑问,为何选择VisualStudioCode?{"version":"0.1.0","command":"make

  9. 企业发行版在Swift App中与iOS8不相称

    我在使用我的swift应用程序在iOS8设备上运行Enterprise构建时遇到问题.如果我使用非企业帐户进行代码签名,它似乎工作正常.有人遇到过这个问题吗?

  10. Glassware auth:android.accounts.OperationCanceledException“不允许共享凭据:取消.”

    MirrorPOSTURL末尾的用户名是否应该与特定内容匹配,或者我们可以自由使用我们自己的东西吗?解决方法要检查几件事:>您的应用程序的软件包名称是否与提交Glassware时提供的软件包名称完全匹配?>您是否通过MyGlass至少安装了一次提交的APK,而不是总是用adb侧载它?确保卸载APK,然后通过在MyGlass中打开它来安装它,以便正确设置权限;从那时起,您可以通过将ad替换为adb来继续开发.

随机推荐

  1. c# – (wpf)Application.Current.Resources vs FindResource

    所以,我正在使用C#中的WPF创建一个GUI.它看起来像这样:它现在还没有完成.这两行是我尝试制作一种数据表,它们在XAML中是硬编码的.现在,我正在C#中实现添加新的水果按钮功能.我在XAML中有以下样式来控制行的背景图像应该是什么样子:因此,在代码中,我为每列col0,col1和col2创建一个图像,如果我使用以下代码,它添加了一个如下所示的新行:如你所见,它不太正确……为什么一个似乎忽略了一些属性而另一个没有?

  2. c# – 绑定DataGridTemplateColumn

    似乎我已经打了个墙,试图在DataGrid上使用DataTemplates.我想要做的是使用一个模板来显示每个单元格的两行文本.但是似乎无法以任何方式绑定列.以下代码希望显示我想做的事情.注意每个列的绑定:模板列没有这样的东西,因此,这个xaml不可能工作.我注定要将整个DataTemplate复制到每个列,只是对每个副本都有不同的约束?解决方法我不完全确定你想要做什么,但如果您需要获取整行的DataContext,可以使用RelativeSource绑定来移动视觉树.像这样:

  3. c# – 学习设计模式的资源

    最近我来到了这个设计模式的概念,并对此感到非常热情.你能建议一些帮助我深入设计模式的资源吗?

  4. c# – 是否有支持嵌入HTML页面的跨操作系统GUI框架?

    我想开发一个桌面应用程序来使用跨系统,是否有一个GUI框架,允许我为所有3个平台编写一次代码,并具有完全可脚本化的嵌入式Web组件?我需要它有一个API来在应用程序和网页之间进行交流.我知道C#,JavaScript和一些python.解决方法Qt有这样的事情QWebView.

  5. c# – 通过字符串在对象图中查找属性

    我试图使用任意字符串访问嵌套类结构的各个部分.给出以下(设计的)类:我想要从Person对象的一个实例的“PersonsAddress.HousePhone.Number”获取对象.目前我正在使用反思来做一些简单的递归查找,但是我希望有一些忍者有更好的想法.作为参考,这里是我开发的(crappy)方法:解决方法您可以简单地使用标准的.NETDataBinder.EvalMethod,像这样:

  6. c# – 文件下载后更新页面

    FamilyID=0a391abd-25c1-4fc0-919f-b21f31ab88b7&displaylang=en&pf=true它呈现该页面,然后使用以下元刷新标签来实际向用户提供要下载的文件:你可能需要在你的应用程序中做类似的事情.但是,如果您真的有兴趣在文件完全下载后执行某些操作,那么您的运气不佳,因为没有任何事件可以与浏览器进行通信.执行此操作的唯一方法是上传附件时使用的AJAXupload.

  7. c# – 如何在每个机器应用程序中实现单个实例?

    我必须限制我的.net4WPF应用程序,以便每台机器只能运行一次.请注意,我说每个机器,而不是每个会话.我使用一个简单的互斥体实现单实例应用程序,直到现在,但不幸的是,这样一个互斥是每个会话.有没有办法创建机器互连,还是有其他解决方案来实现每个机器应用程序的单个实例?

  8. c# – WCF和多个主机头

    我的雇主网站有多个主机名,都是同一个服务器,我们只是显示不同的皮肤来进行品牌宣传.不幸的是,在这种情况下,WCF似乎不能很好地工作.我试过overridingthedefaulthostwithacustomhostfactory.这不是一个可以接受的解决方案,因为它需要从所有主机工作,而不仅仅是1.我也看过thisblogpost,但是我无法让它工作,或者不是为了解决我的问题.我得到的错误是“这

  9. c# – ASP.NET MVC模型绑定与表单元素名称中的虚线

    我一直在搜索互联网,试图找到一种方式来容纳我的表单元素的破折号到ASP.NET的控制器在MVC2,3或甚至4中的默认模型绑定行为.作为一名前端开发人员,我更喜欢在我的CSS中使用camelCase或下划线进行破折号.在我的标记中,我想要做的是这样的:在控制器中,我会传入一个C#对象,看起来像这样:有没有办法通过一些正则表达式或其他行为来扩展Controller类来适应这种情况?我讨厌这样的事实,我必须这样做:甚至这个:思考?

  10. c# – 用户界面设计工具

    我正在寻找一个用户界面设计工具来显示文档中可能的GUI.我不能生成代码.我知道MicrosoftVisio提供了一个功能.但有什么办法吗?您使用哪种软件可视化GUI?

返回
顶部