来自调用线程的Task.ContinueWith

3
我试图从创建任务的线程(不是GUI线程)中执行ContinueWith中的Func。我尝试了这段代码:
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());

var scheduler = TaskScheduler.Current.FromCurrentSynchronizationContext();
Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId);
var t = Task.Factory.StartNew(() =>
{
    Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId);
})
.ContinueWith(
    _ => Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId),
    // Specify where to execute the continuation
    scheduler
);

t.Wait();

但是调用线程和.ContinueWith线程是不同的。有什么想法为什么? 我得到了以下结果:
1 3 3
看起来传递调度程序导致ContinueWith从执行实际任务的线程中执行,而我希望它从创建任务的线程中执行,即在这种情况下为1。
谢谢

你能解释一下为什么你想要这样做吗? - Yuval Itzchakov
如果您有一个当前的同步上下文,这段代码将在t.Wait();处发生死锁,因为等待不会处理已发布的任务。 - acelent
2个回答

5
您可以使用 TaskContinuationOptions.ExecuteSynchronously
ContinueWith(() => { ... }, TaskContinuationOptions.ExecuteSynchronously);
ExecuteSynchronously 指示程序尝试在执行源任务的线程上运行继续任务。而在调用 Task.Factory.StartNew 后执行继续任务,该线程将是线程池线程。
但要注意,这只是一个提示,框架不总是遵循你的请求。因此,你不应该构建代码以使在相同线程上运行成为必要条件。

1
是的,问题是我需要异步执行它。而且我没有太多选择,我正在维护一些遗留代码 :( - Davita
@Davita 看一下修改。ExecuteSynchronously 并不意味着它在同步运行。 - mrahhal
我没有注意到你只在继续中使用调度程序。你提供调度程序的原因是什么(没有同步上下文,对吗)? - mrahhal
1
我认为OP不想在同一个线程上安排继续执行前面的任务,他希望从创建该任务的线程中执行。 - Yuval Itzchakov
是的,我后来有点明白了,但答案已经被接受了,所以我有点困惑。@Davita,你得到你想要的了吗?如果你不在具有FromCurrentSynchronizationContext的环境中(如WPF、winforms、asp.net...),你不能使用它。它会返回null,对于没有任何效果。 - mrahhal
显示剩余2条评论

3

SynchronizationContext 类使用线程池。 如果您需要单线程同步上下文,则应使用 DispatcherSynchronizationContextWindowsFormsSynchronizationContext 或编写符合您需求的自定义同步上下文。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接