如何同步运行连续任务
本文关键字:运行 连续 任务 同步 何同步 | 更新日期: 2023-09-27 18:20:31
我声明了一个方法,该方法应该异步运行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
解决方案。我将保留我的方法的"微小"逻辑或循环复杂性,我的意思是,它只是一个我在其上传递
Acton
的方法,没有在该方法或其他可能导致最终用户编写超过Action
的复杂事物之外声明委托。该方法本身应该自动执行所有所需的操作,以同步地执行延续任务,而不需要外部的复杂性。
因此,正如我从问题和评论中了解到的,您希望在线程池线程(后台线程)上运行任务1,并且希望在UI线程上运行任务2(它是任务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线程初始化它。
请注意,控件将立即返回给WaitUntilLoadedAsync
的调用方,并且回调将在任务1完成后在UI线程上执行。
如果只想在从UI线程调用WaitUntilLoadedAsync
的情况下在UI线程上执行延续任务(否则在线程池线程上执行),则将thread_scheduler
定义如下:
var thread_scheduler = SynchronizationContext.Current == null
? TaskScheduler.Default
: TaskScheduler.FromCurrentSynchronizationContext();
听起来你在寻找TaskContinuationsOptions.ExecuteSynchronously
根据MSDN:
指定应同步执行延续任务。指定此选项后,继续在导致先行任务转换到其最终状态的同一线程上运行。如果在创建延续时先行件已经完成,则延续将在创建延续的线程上运行。如果先行件的CancellationTokenSource被释放在finally块中(在Visual Basic中为finally),则带有此选项的延续将在该finally块上运行。只有非常短的持续运行才应该同步执行。
因为任务是同步执行的,所以不需要调用task等方法。等待以确保调用线程等待任务完成。
要使用它,只需使用过载.ContinueWith(Action<task>, TaskContinuationOptions)
将其作为标志传递即可
然而,如果执行父线程的线程被中止(这是不常见的),这将不是同步的。