【问题标题】:Task.ContinueWith from calling threadTask.ContinueWith 来自调用线程
【发布时间】:2016-03-25 20:01:49
【问题描述】:

我正在尝试从创建任务的线程(不是 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。

谢谢

【问题讨论】:

  • 你能解释一下为什么你想这样做吗?
  • 如果你有一个当前的同步上下文,这段代码会在t.Wait();死锁,因为等待不会处理发布的任务。

标签: c# multithreading asynchronous task-parallel-library


【解决方案1】:

你可以使用TaskContinuationOptions.ExecuteSynchronously:

ContinueWith(() => { ... }, TaskContinuationOptions.ExecuteSynchronously);

ExecuteSynchronously 告诉它 try 并在最后执行先前任务的任何线程上运行延续。在Task.Factory.StartNew 调用之后继续执行的情况下,该线程将是线程池线程。

但您必须注意,这只是一个提示,框架不会始终满足您的要求。所以你不应该构建你的代码,以便在同一个线程上运行成为必要。

【讨论】:

  • 是的,问题是我需要异步执行。而且我没有太多选择,我正在维护一些遗留代码:(
  • @Davita 查看编辑。 ExecuteSynchronously 不代表同步运行。
  • 正如我所说,这只是一个提示,并且由于您明确地给它一个调度程序,因此该调度程序决定了哪个线程来执行它。我相信当您提供调度程序时,您想要的事情无法完成。
  • 我错过了你只在后续使用调度程序。您是否有理由首先提供该调度程序(没有正确的同步上下文)?
  • 我不认为 OP 想要将延续安排在与先前任务相同的线程上,他希望它从创建该任务的线程中执行。
【解决方案2】:

SynchronizationContext 类使用线程池。 如果您需要单线程同步上下文,那么您应该使用 DispatcherSynchronizationContextWindowsFormsSynchronizationContext 或编写您自己的同步上下文以根据您的需要工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多