如何运行同步一个延续任务?
How to run synchronouslly a continuation Task?
我声明了一个应该 运行 异步 Task
的方法,然后,当 Task
完成时,运行 指定的委托 同步.
C# 示例:
private void WaitUntilLoadedAsync(Process p, Action callback, int timeout = 1500)
{
Task.Factory.StartNew(() => ProcessUtil.WaitUntilLoaded(p, timeout)).
ContinueWith(() => callback.Invoke()).RunSynchronously();
}
VB.Net 示例:
Private Sub WaitUntilLoadedAsync(ByVal p As Process,
ByVal callback As Action,
Optional ByVal timeout As Integer = 1500)
Task.Factory.StartNew(Sub() ProcessUtil.WaitUntilLoaded(p, timeout)).
ContinueWith(Sub() callback.Invoke()).RunSynchronously()
End Sub
但是,RunSynchronously
方法抛出一个 System.InvalidOperationException
异常,告诉我延续 Task
不能 运行 同步。
那我该怎么办呢?
备注:
我能够支持 Async
/Await
个解决方案。
我将保留我的方法的 "tiny" 逻辑或圈复杂度,我的意思是,它只是我传递 Acton
的方法,没有声明委托在方法之外或其他可能导致最终用户编写的内容超过 Action
的复杂内容。该方法本身应该自动执行所有必需的操作以同步执行该连续任务,外部没有复杂性。
听起来您正在寻找 TaskContinuationsOptions.ExecuteSynchronously
根据 MSDN:
Specifies that the continuation task should be executed synchronously. With this option specified, the continuation runs on the same thread that causes the antecedent task to transition into its final state. If the antecedent is already complete when the continuation is created, the continuation will run on the thread that creates the continuation. If the antecedent's CancellationTokenSource is disposed in a finally block (Finally in Visual Basic), a continuation with this option will run in that finally block. Only very short-running continuations should be executed synchronously.
Because the task executes synchronously, there is no need to call a method such as Task.Wait to ensure that the calling thread waits for the task to complete.
要使用它,只需使用重载将其作为标志传递即可 .ContinueWith(Action<task>, TaskContinuationOptions)
但是,如果执行父线程的线程中止(这种情况不常见),这将不是同步的。
因此,据我从问题和评论中了解到,您想 运行 线程池线程(后台线程)上的任务 1 并且您想要 运行 任务 2(哪个是 UI 线程上任务 1) 的延续。
这里是你如何做到的:
private void WaitUntilLoadedAsync(Process p, Action callback, int timeout = 1500)
{
var thread_scheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() => ProcessUtil.WaitUntilLoaded(p, timeout)).
ContinueWith(t => callback.Invoke(), CancellationToken.None, TaskContinuationOptions.None,
thread_scheduler);
}
这段代码正在做的是它要求 TPL 运行 调度程序上的延续任务,它将在 UI 线程中执行任务。
这假定 WaitUntilLoadedAsync
是从 UI 线程调用的。如果不是这种情况,只需将 thread_schedular
设为实例变量(或在可从此方法访问的某个范围内),并确保从 UI 线程对其进行初始化。
请注意,控件会立即return到WaitUntilLoadedAsync
的调用者,回调会在任务1完成后在UI线程上执行。
如果仅当从 UI 线程调用 WaitUntilLoadedAsync
时才想在 UI 线程上执行延续任务(否则在线程池线程上执行) , 然后定义 thread_scheduler
如下:
var thread_scheduler = SynchronizationContext.Current == null
? TaskScheduler.Default
: TaskScheduler.FromCurrentSynchronizationContext();
我声明了一个应该 运行 异步 Task
的方法,然后,当 Task
完成时,运行 指定的委托 同步.
C# 示例:
private void WaitUntilLoadedAsync(Process p, Action callback, int timeout = 1500)
{
Task.Factory.StartNew(() => ProcessUtil.WaitUntilLoaded(p, timeout)).
ContinueWith(() => callback.Invoke()).RunSynchronously();
}
VB.Net 示例:
Private Sub WaitUntilLoadedAsync(ByVal p As Process,
ByVal callback As Action,
Optional ByVal timeout As Integer = 1500)
Task.Factory.StartNew(Sub() ProcessUtil.WaitUntilLoaded(p, timeout)).
ContinueWith(Sub() callback.Invoke()).RunSynchronously()
End Sub
但是,RunSynchronously
方法抛出一个 System.InvalidOperationException
异常,告诉我延续 Task
不能 运行 同步。
那我该怎么办呢?
备注:
我能够支持
Async
/Await
个解决方案。我将保留我的方法的 "tiny" 逻辑或圈复杂度,我的意思是,它只是我传递
Acton
的方法,没有声明委托在方法之外或其他可能导致最终用户编写的内容超过Action
的复杂内容。该方法本身应该自动执行所有必需的操作以同步执行该连续任务,外部没有复杂性。
听起来您正在寻找 TaskContinuationsOptions.ExecuteSynchronously
根据 MSDN:
Specifies that the continuation task should be executed synchronously. With this option specified, the continuation runs on the same thread that causes the antecedent task to transition into its final state. If the antecedent is already complete when the continuation is created, the continuation will run on the thread that creates the continuation. If the antecedent's CancellationTokenSource is disposed in a finally block (Finally in Visual Basic), a continuation with this option will run in that finally block. Only very short-running continuations should be executed synchronously.
Because the task executes synchronously, there is no need to call a method such as Task.Wait to ensure that the calling thread waits for the task to complete.
要使用它,只需使用重载将其作为标志传递即可 .ContinueWith(Action<task>, TaskContinuationOptions)
但是,如果执行父线程的线程中止(这种情况不常见),这将不是同步的。
因此,据我从问题和评论中了解到,您想 运行 线程池线程(后台线程)上的任务 1 并且您想要 运行 任务 2(哪个是 UI 线程上任务 1) 的延续。
这里是你如何做到的:
private void WaitUntilLoadedAsync(Process p, Action callback, int timeout = 1500)
{
var thread_scheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() => ProcessUtil.WaitUntilLoaded(p, timeout)).
ContinueWith(t => callback.Invoke(), CancellationToken.None, TaskContinuationOptions.None,
thread_scheduler);
}
这段代码正在做的是它要求 TPL 运行 调度程序上的延续任务,它将在 UI 线程中执行任务。
这假定 WaitUntilLoadedAsync
是从 UI 线程调用的。如果不是这种情况,只需将 thread_schedular
设为实例变量(或在可从此方法访问的某个范围内),并确保从 UI 线程对其进行初始化。
请注意,控件会立即return到WaitUntilLoadedAsync
的调用者,回调会在任务1完成后在UI线程上执行。
如果仅当从 UI 线程调用 WaitUntilLoadedAsync
时才想在 UI 线程上执行延续任务(否则在线程池线程上执行) , 然后定义 thread_scheduler
如下:
var thread_scheduler = SynchronizationContext.Current == null
? TaskScheduler.Default
: TaskScheduler.FromCurrentSynchronizationContext();