我正在努力掌握C#/ .NET中的异步编程。我在布朗大学的网站上读了一篇关于cs168课程的文章(link),该课程将异步编程定义为同一线程中的交错任务。它说,“现在我们可以引入异步模型......在这个模型中,任务彼此交错,但在一个控制线程中”,并在图中非常清楚地显示交错。但我似乎无法在.NET中的同一个线程中交错两个任务。有没有办法做到这一点?
我写了一些简单的应用程序试图测试这个理论,但我不确定我是否正确地做到了。主程序经常输出到屏幕,使用Thread.Sleep()
来模拟工作。异步任务也是如此。如果使用多个线程,则输出是交错的。但我正试图在一个线程上进行测试。
我有一个WPF应用程序,它运行UI线程上的所有内容,但任务和主程序始终按顺序输出。我创建并启动这样的任务:
var taskFactory = new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext());
var task = taskFactory.StartNew(workDelegate);
我有一个控制台应用程序,它使用Task.Run(workDelegate);
启动任务委托,但是它在不同的线程池线程上运行它们。我不知道如何使它们都在同一个线程上运行。如果我尝试在WPF中使用的相同方法,我会得到一个运行时InvalidOperationException,“当前的SynchronizationContext可能不会被用作TaskScheduler”。
答案 0 :(得分:4)
多个任务不会在单个线程上自动交错。为此,您必须在任务代码中指定允许线程切换到另一个任务的点。您可以通过await Task.Yield
等机制执行此操作。如果您在单个线程上运行,该线程将无法允许其他工作进展,除非它明确地产生。
当您使用TaskScheduler
启动每项任务时,WPF中的消息泵会调度每个任务在UI线程上运行,它们将按顺序运行。
我有一个控制台应用程序,它使用Task.Run(workDelegate);启动任务委托,但是它在不同的线程池线程上运行它们。我不知道如何让它们在同一个线程上运行。
您需要在线程中安装自定义SynchronizationContext
,以便将工作发布到该线程。
答案 1 :(得分:0)
您无法在同一个线程池线程中运行两个并发任务。每个线程池线程一次可以运行一个任务。如果你想在一个线程中做两件事,我现在看到你的选择: 1.将这两件事合并为一个任务 2.创建两个任务,一个依赖于另一个任务。所以最终他们会相继跑完。默认情况下,它不能保证它们会在同一个线程中运行,但你不应该依赖它。
我不清楚你想做什么。根据书籍,用户界面和你的WPF的线程应该做任何繁重的数字处理工作。它应该处理UI并组织工作线程/任务。您可以使用async在后台开始操作。