- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
任务并行库非常棒,在过去的几个月里我经常使用它。然而,有件事确实困扰着我:事实上 TaskScheduler.Current
是默认的任务计划程序,而不是 TaskScheduler.Default
。乍一看,这在文档或示例中绝对不明显。
Current
可能会导致微妙的错误,因为它的行为会根据您是否在另一个任务中而变化。这不容易确定。
假设我正在编写一个异步方法库,使用基于事件的标准异步模式来在原始同步上下文上发出完成信号,与 .NET Framework 中的 XxxAsync 方法完全相同(例如 DownloadFileAsync
)。我决定使用任务并行库来实现,因为使用以下代码实现此行为非常容易:
public class MyLibrary
{
public event EventHandler SomeOperationCompleted;
private void OnSomeOperationCompleted()
{
SomeOperationCompleted?.Invoke(this, EventArgs.Empty);
}
public void DoSomeOperationAsync()
{
Task.Factory.StartNew(() =>
{
Thread.Sleep(1000); // simulate a long operation
}, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default)
.ContinueWith(t =>
{
OnSomeOperationCompleted(); // trigger the event
}, TaskScheduler.FromCurrentSynchronizationContext());
}
}
到目前为止,一切正常。现在,让我们通过在 WPF 或 WinForms 应用程序中单击按钮来调用此库:
private void Button_OnClick(object sender, EventArgs args)
{
var myLibrary = new MyLibrary();
myLibrary.SomeOperationCompleted += (s, e) => DoSomethingElse();
myLibrary.DoSomeOperationAsync(); // call that triggers the event asynchronously
}
private void DoSomethingElse() // the event handler
{
//...
Task.Factory.StartNew(() => Thread.Sleep(5000)); // simulate a long operation
//...
}
在这里,编写库调用的人选择在操作完成时启动一个新的任务
。没什么不寻常的。他或她遵循网络上随处可见的示例,只需使用 Task.Factory.StartNew
而不指定 TaskScheduler
(并且没有简单的重载可以在第二个参数中指定它) )。 DoSomethingElse
方法在单独调用时工作正常,但一旦被事件调用,UI 就会卡住,因为 TaskFactory.Current
将重用我的库中的同步上下文任务调度程序继续。
找出这一点可能需要一些时间,特别是如果第二个任务调用隐藏在某些复杂的调用堆栈中。当然,一旦您知道一切是如何工作的,这里的修复就很简单:始终为您希望在线程池上运行的任何操作指定TaskScheduler.Default。然而,也许第二个任务是由另一个外部库启动的,不知道这种行为,并且在没有特定调度程序的情况下天真地使用 StartNew
。我预计这种情况会很常见。
在我认真思考之后,我无法理解编写 TPL 的团队选择使用 TaskScheduler.Current
而不是 TaskScheduler.Default
作为默认值:
Default
不是默认值!而且文档严重缺乏。Current
使用的真正任务调度程序取决于调用堆栈!这种行为很难保持不变。StartNew
指定任务计划程序很麻烦,因为您必须首先指定任务创建选项和取消标记,从而导致行长且可读性较差。这可以通过编写扩展方法或创建使用 Default
的 TaskFactory
来缓解。我知道这个问题可能听起来很主观,但我找不到一个很好的客观论据来解释为什么这种行为是这样的。我确信我在这里遗漏了一些东西:这就是我向你求助的原因。
最佳答案
我认为当前的行为是有道理的。如果我创建自己的任务计划程序,并启动一些启动其他任务的任务,我可能希望所有任务都使用我创建的计划程序。
我同意,有时从 UI 线程启动任务使用默认调度程序有时不使用,这很奇怪。但我不知道如果我来设计它,我该如何让它变得更好。
关于您的具体问题:
new Task(lambda).Start(scheduler)
。这样做的缺点是,如果任务返回某些内容,则必须指定类型参数。 TaskFactory.Create
可以为您推断类型。Dispatcher.Invoke()
而不是使用 TaskScheduler.FromCurrentSynchronizationContext()
。关于c# - 为什么 TaskScheduler.Current 是默认的 TaskScheduler?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6800705/
我有一个 jQuery 日期选择器。我想将默认日期设置为“当前月份、当前日期(当前年份-18)”,但在设置 defaultDate 属性时遇到问题。显示的默认年份是 1920 年,据说是 1995 年
我有下面的 C 程序来实现升序链表。问题出在 buildList() 函数中,因此您可以忽略除 main() 和 buildList() 之外的其他函数。 #include #include stru
嗯,想象一下 current.txt 文件: asdf base.txt 文件: asdf 其他.txt文件: asdf 当我进行三向 merge 时 git merge-file current.t
我试图在鼠标悬停时生成一个 :after 伪元素。例如: .email{ width:100px; overflow:hidden; text-overflow:ellipsi
为什么 $('a.current').removeClass('current'); 不适用于此 jquery 选项卡? http://jsfiddle.net/laukstein/ytnw9/8/
我正在创建一个应用程序(Outlook 的 Office 加载项) 我遇到的问题是更新我的屏幕。我知道我需要调用 Dispatcher,但是它在我的 ViewModel 中始终为 null p
我为客户开发网络和移动应用程序。在我当前的架构中,许多资源在 Web 访问和移动访问之间共享。 aspx 页面可以显示在网络上,也可以在移动应用程序中调用 WebView 。我的问题是: WebOpe
我通过调用 IEnumerable.GetEnumerator() 得到了一个枚举器,然后我称它为MoveNext()直到它返回false,然后访问它的Current属性(property)。令我惊讶
我正在尝试动态查找当前运行的函数(此函数)的名称,即 (defun my-func () (remove-hook 'some-hook this-function) (do-
阅读了短语 "The current SynchronizationContext is a property of the current thread" correct" ,我有点懵了…… 在 V
集成 IOS STRIPE TERMINAL SDK对于BBPOS Chipper 2X BT使用 swift 。我们已经开发并测试了该系统,并且运行良好。但是当我们将它交给其他国家的客户时,他们收到
当我在训练期间编写的类上实现 IEnumerable 和 IEnumerator 时,我注意到我需要为属性“Current”指定两个实现。 public class PeopleEnumerator
我原以为对实现了 IEnumerable 的空集合执行以下代码会抛出异常: var enumerator = collection.GetEnumerator(); enumerator.MoveNe
应Application.Current.Shutdown()不用作关闭 WPF 应用程序的最佳实践? 我有一个小的多窗口应用程序,“关机”似乎对我所有的退出命令都很好。但是,我被告知要始终使用 Ap
在 XPath 1.0 中,有一个函数 current() 可以派上用场,当我根据我当时所在的节点引用 XML 中其他地方的节点时。我的 XML 具有如下结构:
在 MVC 中,这两者有什么区别? 它们看起来相同,甚至返回相同的类型/类System.Web.Security.RolePrincipal,但有一些微妙之处。 例如。当针对通过 ClaimsPrin
这个问题在这里已经有了答案: What is the difference between an App and Application in c#.net? (1 个回答) 关闭 7 年前。 这两
我正在为我的团队开发一个代码生成器 (VSIX),在我与 VSIX 可扩展性框架作斗争之后,我打算使用 Roslyn 作为基础引擎。 我的代码生成器目前能够为解决方案生成一个新的 csproj,并且能
为什么 $('a.current').parent('li').addClass('current'); 和 $(this).hasClass('current')。 parent('li').add
当我使用 Xcode 调试我的 iOS 程序时,gdb 将其显示在控制台 View 上,并且没有发生任何错误。 我只想知道输出“Current language: auto; currently ob
我是一名优秀的程序员,十分优秀!