如何强制Task.Factory.StartNew到后台线程?

我已经看到了许多与此相似的其他问题,但在那里找不到我的答案。

我的问题是我用以下流程创建线程:

private void btn_Click(object sender, EventArgs e) { service.GetCount( (count, ex) => { if (ex != null) return; for (int i = 0; i < count; i++) { service.Get(onItemReceived, i); } } ); } public void GetCount(Action callback) { var callingThread = TaskScheduler.FromCurrentSynchronizationContext(); Func action = () => { return client.GetCount(); // Synchronous method, could take a long time }; Action<Task> completeAction = (task) => { Exception ex = (task.Exception != null) ? task.Exception.InnerException : task.Exception; if (callback != null) callback(task.Result, ex); }; Task.Factory.StartNew(action).ContinueWith(completeAction, callingThread); } public void Get(Action callback, int index) { var callingThread = TaskScheduler.FromCurrentSynchronizationContext(); Func action = () => { return client.Get(index); // Synchronous method, could take a long time }; Action<Task> completeAction = (task) => { Exception ex = (task.Exception != null) ? task.Exception.InnerException : task.Exception; if (callback != null) callback(task.Result, ex); }; Task.Factory.StartNew(action).ContinueWith(completeAction, callingThread); } 

这样,我的每个服务的异步方法都会回调它们最初被调用的线程(通常是UI线程)。 所以我模拟了await / async关键字是如何工作的(我不能使用.NET 4.5)。

这种模式的问题在于,在第一次调用“ContinueWith”后,我莫名其妙地被锁定到UI线程。 因此,在这种情况下,如果我尝试为每个进程生成5个线程同步函数Get ,它们将逐个执行而不是并行执行,即使我尝试指定TaskCreationOptions.LongRunning,它们也会阻塞UI线程。

我第一次调用Task.Factory.StartNew时就不会发生这种情况,它只发生在第一次回调中的后续调用中。

为了强制启动新线程,您应该在对Task.Factory.StartNew的调用中指定TaskScheduler.Default,如下所示:

 Task.Factory.StartNew(action, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).ContinueWith(completeAction); 

在我的测试中,您不需要指定TaskCreationOptions.LongRunning来强制后台线程,尽管它不应该受到伤害。