我只是想知道方法是什么?在哪种情况下我可以使用此方法。
我最初的想法是RunSynchronously
是为了调用异步方法并同步运行该方法而不会引起像.wait()
那样的死锁问题。
但是,根据MSDN
通常,任务在线程池线程上异步执行,并且不阻塞调用线程。通过调用RunSynchronously()方法执行的任务与当前TaskScheduler关联,并在调用线程上运行。如果目标调度程序不支持在调用线程上运行此任务,则该任务将按调度计划执行,并且调用线程将阻塞,直到任务完成执行为止。
如果任务要在调用线程上运行,为什么这里需要TaskScheduler?
答案 0 :(得分:8)
RunSynchronously
将何时启动任务的决定委托给当前的任务调度程序(或作为参数传递的任务调度程序)。
我不确定为什么要使用它(可能是内部使用或旧式使用),但是很难想到当前 .NET 版本中有用的用例。 @Fabjan has a possible explanation in his comment提问。
RunSynchronously
要求调度程序同步运行它,但随后调度程序可以很好地忽略该提示,并在线程池线程中运行它,您当前的线程将同步阻塞,直到完成为止。
尽管我认为这是常见调度程序(ThreadPoolTaskScheduler和常见UI调度程序)上会发生的事情,但调度程序不必在当前线程上运行它,也不必立即运行它。
RunSynchronously
也将引发异常,如果任务已经开始或已完成/已发生故障(这意味着您将无法在异步方法上使用它)。
此代码可以阐明不同的行为:
Wait
和Result
根本不运行任务,它们只是在当前线程上等待任务完成并阻塞直到完成,因此,如果我们要进行比较,可以进行比较Start
和Wait
至RunSynchronously
:
class Scheduler : TaskScheduler
{
protected override void QueueTask(Task task) =>
Console.WriteLine("QueueTask");
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
Console.WriteLine("TryExecuteTaskInline");
return false;
}
protected override IEnumerable<Task> GetScheduledTasks() => throw new NotImplementedException();
}
static class Program
{
static void Main()
{
var taskToStart = new Task(() => { });
var taskToRunSynchronously = new Task(() => { });
taskToStart.Start(new Scheduler());
taskToRunSynchronously.RunSynchronously(new Scheduler());
}
}
如果您尝试对Start或RunSynchronously
进行注释并运行代码,则会看到Start
尝试将任务排入调度程序,而RunSynchronously
将尝试内联执行该任务并如果失败(返回false),它将排入队列。
答案 1 :(得分:3)
首先让我们看一下这段代码:
public async static Task<int> MyAsyncMethod()
{
await Task.Delay(100);
return 100;
}
//Task.Delay(5000).RunSynchronously(); // bang
//Task.Run(() => Thread.Sleep(5000)).RunSynchronously(); // bang
// MyAsyncMethod().RunSynchronously(); // bang
var t = new Task(() => Thread.Sleep(5000));
t.RunSynchronously(); // works
在此示例中,我们尝试在以下任务上调用RunSynchronously
:
async await
创建的另一个诺言任务创建后它们将具有什么状态?
所有“热”任务均以状态WaitingForActivation
或WaitingToRun
创建,并与任务计划程序相关联。
方法RunSynchronously
仅知道如何处理包含委托且状态为Created
的“冷”任务。
结论:
RunSynchronously
方法可能是在没有“热门”任务或者它们没有被广泛使用并为特定目的而创建时出现的。
我们可能需要使用带有自定义TaskScheduler
的“冷”任务时使用它,否则它就已经过时且无用。
要同步运行“热”任务(我们应该避免),我们可以使用task.GetAwaiter().GetResult()
。作为奖励,它会返回原始异常,而不是AggregateException
的实例。